PHP Professionanal
PHP Professionanal
GoalKicker.com
Disclaimer
400+ pages
Contents
About ....................................................................................................................................................
............................... 1
Chapter 2:
Variables ................................................................................................................................................
.... 9
Chapter 3: Variable
Scope ..................................................................................................................................... 18
Section 5.6: Output a Multidimensional Array with index and value and print into the
table ............................. 37
Chapter 6:
Constants ..............................................................................................................................................
.. 39
Chapter 7: Magic
Constants .................................................................................................................................. 43
Chapter 8:
Comments .............................................................................................................................................
. 45
Chapter 9:
Types .....................................................................................................................................................
.... 46
Section 9.2:
Boolean .................................................................................................................................................
... 46
Section 9.3:
Float ......................................................................................................................................................
... 47
Section 9.4:
Strings ...................................................................................................................................................
... 48
Section 9.5:
Callable .................................................................................................................................................
... 50
Section 9.6:
Resources ..............................................................................................................................................
.. 50
Section 9.9:
Null .......................................................................................................................................................
.... 52
Section 9.10:
Integers .................................................................................................................................................
. 52
Chapter 10:
Operators ..............................................................................................................................................
54
Section 10.12:
Association ............................................................................................................................................
60
Section 10.13: Comparison
Operators ........................................................................................................................ 60
Chapter 11:
References ............................................................................................................................................
67
Chapter 12:
Arrays ....................................................................................................................................................
.. 71
Section 14.5:
array_reduce .........................................................................................................................................
86
Section 16.4: Combining two arrays (keys from one, values from
another) ...................................................... 100
Section 17.1: Create Immutable version of DateTime from Mutable prior PHP
5.6 ............................................ 102
Section 17.3:
getTimestamp .....................................................................................................................................
102
Section 17.4:
setDate .................................................................................................................................................
103
Section 19.1: if
else .....................................................................................................................................................
109
Section 19.3:
while .....................................................................................................................................................
. 109
Section 19.5:
goto ......................................................................................................................................................
110
Section 19.6:
declare ..................................................................................................................................................
110
Section 19.8:
return ....................................................................................................................................................
112
Section 19.9:
for .........................................................................................................................................................
112
Section 19.10:
foreach ................................................................................................................................................
113
Section 19.12:
if ...........................................................................................................................................................
114
Section 19.13:
switch ...................................................................................................................................................
114
Chapter 20:
Loops ....................................................................................................................................................
116
Section 20.1:
continue ...............................................................................................................................................
116
Section 20.2:
break ...................................................................................................................................................
117
Section 20.3:
foreach ................................................................................................................................................
118
Section 20.4:
do...while ..............................................................................................................................................
118
Section 20.5:
for ........................................................................................................................................................
119
Section 20.6:
while .....................................................................................................................................................
120
Chapter 21:
Functions .............................................................................................................................................
121
Section 22.1:
Closures ................................................................................................................................................
125
Section 22.9:
Scope ...................................................................................................................................................
129
Section 25.2:
Substring .............................................................................................................................................
136
Section 26.6:
Interfaces ............................................................................................................................................
149
Section 26.8:
Autoloading .........................................................................................................................................
153
Chapter 27:
Namespaces .....................................................................................................................................
162
Chapter 28:
Sessions ...............................................................................................................................................
165
Chapter 29:
Cookies .................................................................................................................................................
169
Section 29.1: Modifying a
Cookie ............................................................................................................................. 169
Section 30.6: Using Output buer to store contents in a file, useful for reports, invoices
etc .......................... 174
Chapter 31:
JSON ......................................................................................................................................................
177
Section 32.3:
Classmaps ...........................................................................................................................................
187
Section 33.5: Sending multi-dimensional data and multiple files with CurlFile in one
request ......................... 193
Section 33.6: Creating and sending a request with a custom
method ................................................................ 196
Chapter 34:
Reflection ...........................................................................................................................................
198
Chapter 36:
XML .......................................................................................................................................................
. 205
Chapter 37:
SimpleXML ..........................................................................................................................................
212
Section 38.3:
SimpleXML ...........................................................................................................................................
213
Chapter 40:
Traits ....................................................................................................................................................
219
Section 41.6:
Installation ............................................................................................................................................
230
Section 42.4:
__toString() ........................................................................................................................................
234
Section 42.5:
__clone() ............................................................................................................................................
235
Section 42.6:
__invoke() ...........................................................................................................................................
235
Section 42.8:
__debugInfo() ....................................................................................................................................
236
Chapter 44:
Streams ..............................................................................................................................................
246
Chapter 47:
Generators ........................................................................................................................................
263
Section 48.1:
Input .....................................................................................................................................................
. 267
Section 48.2:
Output ..................................................................................................................................................
267
Section 49.2: Converting Unicode characters to their numeric value and/or HTML entities using PHP
..............................................................................................................................................................
............... 269
Chapter 50:
URLs ......................................................................................................................................................
272
Chapter 54:
Closure ................................................................................................................................................
284
Chapter 56: Type juggling and Non-Strict Comparison Issues ......................................................... 294
Chapter 57:
Sockets ................................................................................................................................................
298
Chapter 58:
PDO .......................................................................................................................................................
. 301
Section 58.6:
PDO::lastInsertId() ...............................................................................................................................
306
Chapter 60:
SQLite3 ................................................................................................................................................
316
Section 64.1: Sending Email - The basics, more details, and a full
example ....................................................... 325
Chapter 67:
Localization .......................................................................................................................................
343
Chapter 75:
Imagick ................................................................................................................................................
369
Section 77.2:
Regression ...........................................................................................................................................
373
Section 77.3:
Clustering .............................................................................................................................................
375
Chapter 78:
Cache ....................................................................................................................................................
377
Section 80.1:
SplFixedArray ......................................................................................................................................
383
Chapter 81:
IMAP .....................................................................................................................................................
.. 387
Chapter 83:
WebSockets .......................................................................................................................................
392
Chapter 86:
APCu ......................................................................................................................................................
399
Chapter 88:
PSR ........................................................................................................................................................
401
Chapter 89:
PHPDoc ................................................................................................................................................
403
Section 89.4:
Collections ...........................................................................................................................................
405
Chapter 95:
Debugging ..........................................................................................................................................
417
Section 95.3:
phpinfo() ..............................................................................................................................................
418
Section 95.4:
Xdebug ................................................................................................................................................
418
Section 95.6:
phpversion() ........................................................................................................................................
419
Chapter 97:
Performance .....................................................................................................................................
428
Chapter 98:
Multiprocessing ...............................................................................................................................
432
Chapter 101:
Security ..............................................................................................................................................
437
Chapter 102:
Cryptography ................................................................................................................................. 446
Credits ...................................................................................................................................................
......................... 460
About
Please feel free to share this PDF with anyone for free,
https://goalkicker.com/PHPBook
This PHP Notes for Professionals book is compiled from Stack Overflow
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright
This is an unofficial free book created for educational purposes and is not
affiliated with official PHP group(s) or company(s) nor Stack Overflow. All
company owners
PHP 7.x
PHP 5.x
PHP 4.x
Legacy Versions
Version Supported Until Release Date
2.0 1997-11-01
1.0 1995-06-08
PHP can be used to add content to HTML files. While HTML is processed directly by a web browser,
PHP scripts are
executed by a web server and the resulting HTML is sent to the browser.
The following HTML markup contains a PHP statement that will add Hello World! to the output:
<!DOCTYPE html>
<html>
<head>
<title>PHP!</title>
</head>
<body>
</body>
</html>
When this is saved as a PHP script and executed by a web server, the following HTML will be sent to
the user's
browser:
<!DOCTYPE html>
<html>
<head>
<title>PHP!</title>
</head>
<body>
<p>Hello world!</p>
</body>
</html>
echo also has a shortcut syntax, which lets you immediately print a value. Prior to PHP 5.4.0, this short
syntax only
In real-world applications, all data output by PHP to an HTML page should be properly escaped to
prevent XSS
See also: Strings and PSR-1, which describes best practices, including the proper use of short tags (<?
= ... ?>).
The most widely used language construct to print output in PHP is echo:
echo has a void return, whereas print returns an int with a value of 1
echo can take multiple arguments (without parentheses only), whereas print only takes one argument
their arguments. For cosmetic consistency with functions, parentheses can be included. Extensive
examples of the
C-style printf and related functions are available as well, as in the following example:
See Outputting the value of a variable for a comprehensive introduction of outputting variables in PHP.
In some cases, when working with a web server, overriding the web server's default content type may
be required.
There may be cases where you need to send data as plain text, JSON, or XML, for example.
The header() function can send a raw HTTP header. You can add the Content-Type header to notify the
browser of
header("Content-Type: text/plain");
This will produce a plain text document with the following content:
Hello World
header("Content-Type: application/json");
echo json_encode($data);
This will produce a document of type application/json with the following content:
{"response":"Hello World"}
Note that the header() function must be called before PHP produces any output, or the web server will
have
already sent headers for the response. So, consider the following code:
echo "Hello";
header("Content-Type: text/plain");
echo "World";
Warning: Cannot modify header information - headers already sent by (output started at
When using header(), its output needs to be the first byte that's sent from the server. For this reason
it's important
to not have empty lines or spaces in the beginning of the file before the PHP opening tag <?php. For
the same
reason, it is considered best practice (see PSR-2) to omit the PHP closing tag ?> from files that contain
only PHP and
View the output buffering section to learn how to 'catch' your content into a variable to output later,
for example,
PHP 5.4+ comes with a built-in development server. It can be used to run applications without having
to install a
production HTTP server such as nginx or Apache. The built-in server is only designed to be used for
development
php -S <host/ip>:<port>
Example usage
<?php
2. Run the command php -S localhost:8080 from the command line. Do not include
http://
. This will start a web server listening on port 8080 using the current directory that you are in as the
document root.
3. Open the browser and navigate to http://localhost:8080. You should see your "Hello World" page.
Configuration
To override the default document root (i.e. the current directory), use the -t flag:
E.g. if you have a public/ directory in your project you can serve your project from that directory using
php -S
localhost:8080 -t public/.
Logs
Every time a request is made from the development server, a log entry like the one below is written to
the
command line.
PHP can also be run from command line directly using the CLI (Command Line Interface).
CLI is basically the same as PHP from web servers, except some differences in terms of standard input
and output.
Triggering
1. Standard input. Run the php command without any arguments, but pipe PHP code into it: echo '<?
php echo
2. Filename as argument. Run the php command with the name of a PHP source file as the first
argument: php
hello_world.php
3. Code as argument. Use the -r option in the php command, followed by the code to run. The <?php
open tags
are not required, as everything in the argument is considered as PHP code: php -r 'echo "Hello
world!";'
4. Interactive shell. Use the -a option in the php command to launch an interactive shell. Then, type (or
paste)
PHP code and hit return : $ php -a Interactive mode enabled php > echo "Hello world!"; Hello world!
Output
All functions or controls that produce HTML output in web server PHP can be used to produce output
in the stdout
stream (file descriptor 1), and all actions that produce output in error logs in web server PHP will
produce output in
Example.php
<?php
trigger_error("Stderr 2\n");
print_r("Stdout 3\n");
fwrite(STDERR, "Stderr 4\n");
?>
Stdout 6
STDOUT
Stdout 1
Stdout 3
STDERR
Stderr 4
in /Example.php on line 3
in /Example.php:6
Stack trace:
#0 {main}
Input
Just like most other C-style languages, each statement is terminated with a semicolon. Also, a closing
tag is used to
line of code. For example, we can leave out the closing tag after echo "No error"; in the following
example:
<?php echo "No error"; // no closing tag is needed as long as there is no code below
However, if there is any other code following your PHP code block, the closing tag is no longer
optional:
<?php echo "This will cause an error if you leave out the closing tag"; ?>
<html>
<body>
</body>
</html>
We can also leave out the semicolon of the last statement in a PHP code block if that code block has a
closing tag:
It is generally recommended to always use a semicolon and use a closing tag for every PHP code block
except the
last PHP code block, if no more code follows that PHP code block.
<?php
echo "Here we use a semicolon and a closing tag because more code follows";
?>
<p>Some HTML code goes here</p>
<?php
echo "Here we use a semicolon and a closing tag because more code follows";
?>
<?php
echo "Here we use a semicolon but leave out the closing tag";
There are three kinds of tags to denote PHP blocks in a file. The PHP parser is looking for the opening
and (if
Standard Tags
These tags are the standard method to embed PHP code in a file.
<?php
?>
Echo Tags
These tags are available in all PHP versions, and since PHP 5.4 are always enabled. In previous
versions, echo tags
could only be enabled in conjunction with short tags.
Short Tags
You can disable or enable these tags with the option short_open_tag.
<?
?>
Short tags:
ASP Tags
<%
%>
These are an historic quirk and should never be used. They were removed in PHP 7.0.
Chapter 2: Variables
(Variable variables)
Variables can be accessed via dynamic variable names. The name of a variable can be stored in
another variable,
To turn a variable into a variable variable, you put an extra $ put in front of your variable.
$variableName = 'foo';
$foo = 'bar';
echo $foo;
echo ${$variableName};
echo $$variableName;
//similarly,
$variableName = 'foo';
$$variableName = 'bar';
echo $foo;
echo $$variableName;
echo ${$variableName};
return $a + $b;
$funcName = 'add';
class myClass {
$this->$functionName('Hello World');
${$variableName} = $value;
$fooBar = 'baz';
$varPrefix = 'foo';
Using {} is only mandatory when the name of the variable is itself an expression, like this:
$$$$$$$$DoNotTryThisAtHomeKids = $value;
It's important to note that the excessive usage of variable variables is considered a bad practice by
many
developers. Since they're not well-suited for static analysis by modern IDEs, large codebases with
many
variable variables (or dynamic method invocations) can quickly become difficult to maintain.
In PHP7, dynamic variables, properties, and methods will now be evaluated strictly in left-to-right
order, as opposed
to the mix of special cases in PHP5. The examples below show how the order of evaluation has
changed.
Case 1 : $$foo['bar']['baz']
Case 2 : $foo->$bar['baz']
Case 3 : $foo->$bar['baz']()
Case 4 : Foo::$bar['baz']()
There are different data types for different purposes. PHP does not have explicit type definitions, but
the type of a
variable is determined by the type of the value that is assigned, or by the type that it is casted to. This
is a brief
overview about the types, for a detailed documentation and examples, see the PHP types topic.
There are following data types in PHP: null, boolean, integer, float, string, object, resource and array.
$foo = null;
This invalidates the variable and it's value would be undefined or void if called. The variable is cleared
from memory
Boolean
$foo = true;
$bar = false;
$foo = true;
if ($foo) {
echo "true";
} else {
echo "false";
Integer
An integer is a whole number positive or negative. It can be in used with any number base. The size of
an integer is
Float
Floating point numbers, "doubles" or simply called "floats" are decimal numbers.
$foo = 1.23;
$foo = 10.0;
$bar = -INF;
$bar = NAN;
Array
An array is like a list of values. The simplest form of an array is indexed by integer, and ordered by the
index, with
$bar = ["A", true, 123 => 5]; // Short array syntax, PHP 5.4+
Arrays can also associate a key other than an integer index to a value. In PHP, all arrays are associative
arrays
behind the scenes, but when we refer to an 'associative array' distinctly, we usually mean one that
contains one or
$array = array();
$array["foo"] = "bar";
$array["baz"] = "quux";
$array[42] = "hello";
String
$foo = "bar";
$foo = "bar";
echo $foo[0]; // Prints 'b', the first character of the string in $foo.
Object
An object is an instance of a class. Its variables and methods can be accessed with the -> operator.
$foo = new stdClass(); // create new object of class stdClass, which a predefined, empty class
$foo->bar = "baz";
Resource
Resource variables hold special handles to opened files, database connections, streams, image canvas
areas and
$fp = fopen('file.ext', 'r'); // fopen() is the function to open a file on disk as a resource.
function foo() {
global $bob;
$bob->doSomething();
Are you confused? Good. You've just learned why globals are confusing and considered a bad practice.
If this were a real program, your next bit of fun is to go track down all instances of $bob and hope you
find the right
one (this gets worse if $bob is used everywhere). Worse, if someone else goes and defines $bob (or
you forgot and
reused that variable) your code can break (in the above code example, having the wrong object, or no
object at all,
Since virtually all PHP programs make use of code like include('file.php'); your job maintaining code
like this
Also, this makes the task of testing your applications very difficult. Suppose you use a global variable
to hold your
database connection:
function doSomething() {
global $dbConnector;
$dbConnector->execute("...");
In order to unit test this function, you have to override the global $dbConnector variable, run the tests
and then
/**
* @test
*/
function testSomething() {
global $dbConnector;
assertTrue(foo());
The best way to avoid globals is a philosophy called Dependency Injection. This is where we pass the
tools we
$bob->doSomething();
This is much easier to understand and maintain. There's no guessing where $bob was set up because
the caller is
responsible for knowing that (it's passing us what we need to know). Better still, we can use type
declarations to
restrict what's being passed.
So we know that $bob is either an instance of the Bar class, or an instance of a child of Bar, meaning
we know we
can use the methods of that class. Combined with a standard autoloader (available since PHP 5.3), we
can now go
track down where Bar is defined. PHP 7.0 or later includes expanded type declarations, where you can
also use
Version = 4.1
Superglobal variables
Super globals in PHP are predefined variables, which are always available, can be accessed from any
scope
There is no need to do global $variable; to access them within functions/methods, classes or files.
$GLOBALS
$_SERVER
$_REQUEST
$_POST
$_GET
$_FILES
$_ENV
$_COOKIE
$_SESSION
Although not necessary in PHP however it is a very good practice to initialize variables. Uninitialized
variables have a
default value of their type depending on the context in which they are used:
Boolean
String
$unset_str .= 'abc';
Integer
Float/double
$unset_float += 1.25;
Array
$unset_arr[3] = "def";
Object
$unset_obj->foo = 'bar';
Relying on the default value of an uninitialized variable is problematic in the case of including one file
into another
In PHP, variable values have an associated "truthiness" so even non-boolean values will equate to true
or false.
Here are some fundamental rules for different types of variable values:
Strings with non-zero length equate to true including strings containing only whitepace such as ' '.
$var = '';
Integers equate to true if they are nonzero, while zero equates to false.
$var = -1;
$var = 99;
$var = 0;
$var = null;
$var = '';
$var = '0';
Floating-point values equate to true if they are nonzero, while zero values equates to false.
NAN (PHP's Not-a-Number) equates to true, i.e. NAN == true is true. This is because NAN is a nonzero
floating-point value.
Zero-values include both +0 and -0 as defined by IEEE 754. PHP does not distinguish between +0 and -0
$var = NAN;
$var = floatval('-0');
IDENTICAL OPERATOR
In the PHP Documentation for Comparison Operators, there is an Identical Operator ===. This operator
can be used
to check whether a variable is identical to a reference value:
$var = null;
$var = null;
The identical operator can be used as an alternative to language functions like is_null().
The strpos($haystack, $needle) language function is used to locate the index at which $needle occurs
in
$haystack, or whether it occurs at all. The strpos() function is case sensitive; if case-insensitive find is
what you
The strpos & stripos function also contains third parameter offset (int) which if specified, search will
start this
number of characters counted from the beginning of the string. Unlike strrpos and strripos, the offset
cannot be
negative
a non-zero integer specifying the index if $needle is found somewhere other than the beginning in
$haystack;
and value false if $needle is not found anywhere in $haystack.
Because both 0 and false have truthiness false in PHP but represent distinct situations for strpos(), it is
important to distinguish between them and use the identical operator === to look exactly for false and
not just a
else
else
PHP scope blocks are defined by functions, classes, and a global scope available throughout an
application.
Superglobal variables are defined by PHP and can always be used from anywhere without the global
keyword.
<?php
if (isset($_POST[$key])) {
return $_POST[$key];
return $default;
// retrieves $_POST['username']
echo getPostValue('username');
Static class properties that are defined with the public visibility are functionally the same as global
variables. They
class SomeClass {
}
// The static $counter variable can be read/written from anywhere
SomeClass::$counter += 1;
Functions can also define static variables inside their own scope. These static variables persist through
multiple
function calls, unlike regular variables defined in a function scope. This can be a very easy and simple
way to
class Singleton {
static $instance;
// Second call to this function will not get into the if-statement,
if (!$instance) {
return $instance;
$instance1 = Singleton::getInstance();
$instance2 = Singleton::getInstance();
// Comparing objects with the '===' operator checks whether they are
// the same instance. Will print 'true', because the static $instance
The scope outside of any function or class is the global scope. When a PHP script includes another
(using include
or require) the scope remains the same. If a script is included outside of any function or class, it's
global variables
are included in the same global scope, but if a script is included from within a function, the variables in
the included
Within the scope of a function or class method, the global keyword may be used to create an access
user-defined
global variables.
<?php
$amount_of_log_calls = 0;
function log_message($message) {
global $amount_of_log_calls;
$amount_of_log_calls += 1;
echo $message;
echo $amount_of_log_calls; // 1
echo $amount_of_log_calls; // 2
A second way to access variables from the global scope is to use the special PHP-defined $GLOBALS
array.
The $GLOBALS array is an associative array with the name of the global variable being the key and the
contents of
that variable being the value of the array element. Notice how $GLOBALS exists in any scope, this is
because
$GLOBALS is a superglobal.
function log_message($message) {
// is a superglobal variable.
$GLOBALS['amount_of_log_calls'] += 1;
echo $messsage;
One might ask, why use the $GLOBALS array when the global keyword can also be used to get a global
variable's
value? The main reason is using the global keyword will bring the variable into scope. You then can't
reuse the
Superglobals are built-in variables that are always available in all scopes.
Several predefined variables in PHP are "superglobals", which means they are available in all scopes
throughout a
script. There is no need to do global $variable; to access them within functions or methods.
Introduction
Put simply, these are variables that are available in all scope in your scripts.
This means that there is no need to pass them as parameters in your functions, or store them outside
a block of
What's a superglobal??
As of PHP version 7.1.3 there are 9 superglobal variables. They are as follows:
$GLOBALS
An associative array containing references to all variables which are currently defined in the global
scope
of the script. The variable names are the keys of the array.
Code
function test()
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
var_dump($myLocal);
var_dump($myGlobal);
Output
null
In the above example $myLocal is not displayed the second time because it is declared inside the test()
function
and then destroyed after the function is closed.
Becoming global
function test()
global $myLocal;
$myLocal = "local";
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
The global keyword is a prefix on a variable that forces it to be part of the global scope.
Note that you cannot assign a value to a variable in the same statement as the global keyword. Hence,
why I had to
assign a value underneath. (It is possible if you remove new lines and spaces but I don't think it is
neat. global
function test()
$GLOBALS["myLocal"] = "local";
$myLocal = $GLOBALS["myLocal"];
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
In this example I reassigned $myLocal the value of $GLOBAL["myLocal"] since I find it easier writing a
variable name
rather than the associative array.
$_SERVER
$_SERVER is an array containing information such as headers, paths, and script locations. The entries
in
this array are created by the web server. There is no guarantee that every web server will provide any
of
these; servers may omit some, or provide others not listed here. That said, a large number of these
variables are accounted for in the CGI/1.1 specification, so you should be able to expect those.
C:\wamp64\www\test.php:2:
array (size=36)
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' (length=74)
Client\;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\
System32\Wbem
Managemen'... (length=1169)
There is a lot to take in there so I will pick out some important ones below. If you wish to read about
them all then
I might add them all below one day. Or someone can edit and add a good explanation of them below?
Hint, hint;)
HTTP_USER_AGENT - Contents of the user agent. This is a string which contains all the information
about the
SERVER_ADDR - The IP address of the server, of which the current script is running.
PHP_SELF - The file name of the currently executed script, relative to document root.
REQUEST_TIME_FLOAT - The timestamp of the start of the request, with microsecond precision.
Available since
PHP 5.4.0.
REQUEST_TIME - The timestamp of the start of the request. Available since PHP 5.1.0.
$_GET
An associative array of variables passed to the current script via the URL parameters.
$_GET is an array that contains all the URL parameters; these are the whatever is after the ? in the
URL.
obtained by accessing in this format $_GET["myVar"] and the result of this will be myVal.
// URL = http://www.example.com/index.php?myVar=myVal
This shows how you can access the value from the URL using the $_GET superglobal.
// URL = http://www.example.com/index.php?myVar=myVal&myVar2=myVal2
It is possible to send multiple variables through the URL by separating them with an ampersand (&)
character.
Security risk
It is very important not to send any sensitive information via the URL as it will stay in history of the
computer and
$_POST
An associative array of variables passed to the current script via the HTTP POST method when using
Very similar to $_GET in that data is sent from one place to another.
I'll start by going straight into an example. (I have omitted the action attribute as this will send the
information to
<form method="POST">
</form>
Above is a basic form for which data can be sent. In an real environment the value attribute would not
be set
meaning the form would be blank. This would then send whatever information is entered by the user.
Security risk
Sending data via POST is also not secure. Using HTTPS will ensure that data is kept more secure.
$_FILES
An associative array of items uploaded to the current script via the HTTP POST method. The structure
of
</form>
Note that I omitted the action attribute (again!). Also, I added enctype="multipart/form-data", this is
important
if ($_FILES["myVar"]["error"] == UPLOAD_ERR_OK)
{
if (!file_exists($folderLocation)) mkdir($folderLocation);
move_uploaded_file($_FILES["myVar"]["tmp_name"], "$folderLocation/" .
basename($_FILES["myVar"]["name"]));
This is used to upload one file. Sometimes you may wish to upload more than one file. An attribute
exists for that,
</form>
The input name has square brackets. This is because it is now an array of files and so we are telling the
form
to make an array of the files selected. Omitting the square brackets will result in the latter most file
being set
to $_FILES["myVar"].
The multiple="multiple" attribute. This just tells the browser that users can select more than one file.
if ($_FILES["myVar"]["error"][$i] == UPLOAD_ERR_OK)
if (!file_exists($folderLocation)) mkdir($folderLocation);
move_uploaded_file($_FILES["myVar"]["tmp_name"][$i], "$folderLocation/" .
basename($_FILES["myVar"]["name"][$i]));
case UPLOAD_ERR_INI_SIZE:
php.ini.";
break;
case UPLOAD_ERR_FORM_SIZE:
echo "Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was
case UPLOAD_ERR_PARTIAL:
break;
case UPLOAD_ERR_NO_FILE:
break;
case UPLOAD_ERR_NO_TMP_DIR:
break;
case UPLOAD_ERR_CANT_WRITE:
break;
case UPLOAD_ERR_EXTENSION:
echo "Value: 8; A PHP extension stopped the file upload. PHP does not provide a way to
ascertain which extension caused the file upload to stop; examining the list of loaded extensions
break;
default:
break;
This is a very simple example and doesn't handle problems such as file extensions that aren't allowed
or files
named with PHP code (like a PHP equivalent of an SQL injection). See the documentation.
The first process is checking if there are any files, and if so, set the total number of them to $total.
Using the for loop allows an iteration of the $_FILES array and accessing each item one at a time. If
that file doesn't
encounter a problem then the if statement is true and the code from the single file upload is run.
If an problem is encountered the switch block is executed and an error is presented in accordance with
the error
$_COOKIE
An associative array of variables passed to the current script via HTTP Cookies.
Cookies are variables that contain data and are stored on the client's computer.
Unlike the aforementioned superglobals, cookies must be created with a function (and not be
assigning a value).
In this example a name is specified for the cookie (in this example it is "myVar"), a value is given (in
this example it is
"myVal", but a variable can be passed to assign its value to the cookie), and then an expiration time is
given (in this
Despite the convention for creating a cookie being different, it is accessed in the same way as the
others.
To destroy a cookie, setcookie must be called again, but the expiration time is set to any time in the
past. See
below.
This will unset the cookies and remove it from the clients computer.
$_SESSION
An associative array containing session variables available to the current script. See the Session
functions
Sessions are much like cookies except they are server side.
To use sessions you must include session_start() at the top of your scripts to allow sessions to be
utilised.
Setting a session variable is the same as setting any other variable. See example below.
$_SESSION["myVar"] = "myVal";
When starting a session a random ID is set as a cookie and called "PHPSESSID" and will contain the
session ID for
that current session. This can be accessed by calling the session_id() function.
It is possible to destroy session variables using the unset function (such that
unset($_SESSION["myVar"]) would
The alternative is to call session_destory(). This will destroy the entire session meaning that all session
variables
$_REQUEST
An associative array that by default contains the contents of $_GET, $_POST and $_COOKIE.
As the PHP documentation states, this is just a collation of $_GET, $_POST, and $_COOKIE all in one
variable.
Since it is possible for all three of those arrays to have an index with the same name, there is a setting
in the
php.ini file called request_order which can specify which of the three has precedence.
For instance, if it was set to "GPC", then the value of $_COOKIE will be used, as it is read from left to
right meaning
the $_REQUEST will set its value to $_GET, then $_POST, and then $_COOKIE and since $_COOKIE is
last that is the value
that is in $_REQUEST.
$_ENV
An associative array of variables passed to the current script via the environment method.
These variables are imported into PHP's global namespace from the environment under which the PHP
parser is running. Many are provided by the shell under which PHP is running and different systems
are
likely running different kinds of shells, a definitive list is impossible. Please see your shell's
Other environment variables include the CGI variables, placed there regardless of whether PHP is
running
Anything stored within $_ENV is from the environment from which PHP is running in.
See this answer for more information on why $_ENV is not populated.
$GLOBALS
$_REQUEST
$_GET
$_POST
$_FILES
$_SERVER
$_ENV
$_COOKIE
$_SESSION
<?php
$a = 10;
function foo(){
echo $GLOBALS['a'];
?>
$_REQUEST: This SuperGlobal Variable is used to collect data submitted by a HTML Form.
<?php
if(isset($_REQUEST['user'])){
echo $_REQUEST['user'];
//This will print value of HTML Field with name=user submitted using POST and/or GET MEthod
?>
$_GET: This SuperGlobal Variable is used to collect data submitted by HTML Form with get method.
<?php
if(isset($_GET['username'])){
echo $_GET['username'];
//This will print value of HTML field with name username submitted using GET Method
?>
$_POST: This SuperGlobal Variable is used to collect data submitted by HTML Form with post method.
<?php
if(isset($_POST['username'])){
echo $_POST['username'];
//This will print value of HTML field with name username submitted using POST Method
?>
$_FILES: This SuperGlobal Variable holds the information of uploaded files via HTTP Post method.
<?php
if($_FILES['picture']){
echo "<pre>";
print_r($_FILES['picture']);
echo "</pre>";
/**
This will print details of the File with name picture uploaded via a form with method='post and with
enctype='multipart/form-data'
Details includes Name of file, Type of File, temporary file location, error code(if any error
Eg.
Array
(
[0] => Array
[error] => 0
*/
?>
$_SERVER: This SuperGlobal Variable holds information about Scripts, HTTP Headers and Server Paths.
<?php
echo "<pre>";
print_r($_SERVER);
echo "</pre>";
/**
on my local XAMPP
Array
[HTTP_UPGRADE_INSECURE_REQUESTS] => 1
Chrome/52.0.2743.82 Safari/537.36
[SERVER_PORT] => 80
[CONTEXT_PREFIX] =>
[QUERY_STRING] =>
*/
?>
$_ENV: This SuperGlobal Variable Shell Environment Variable details under which the PHP is running.
$_COOKIE: This SuperGlobal Variable is used to retrieve Cookie value with given Key.
<?php
$cookie_name = "data";
if(!isset($_COOKIE[$cookie_name])) {
else {
/**
Output
*/
?>
$_SESSION: This SuperGlobal Variable is used to Set and Retrieve Session Value which is stored on
Server.
<?php
session_start();
/**
*/
$_SESSION["user_token"] = "d5f1df5b4dfb8b8d5f";
echo "Session is saved successfully";
/**
Output
*/
?>
Variable
To build a dynamic and interactive PHP program, it is useful to output variables and their values. The
PHP language
allows for multiple methods of value output. This topic covers the standard methods of printing a
value in PHP and
echo and print are language constructs, not functions. This means that they don't require parentheses
around the
argument like a function does (although one can always add parentheses around almost any PHP
expression and
thus echo("test") won't do any harm either). They output the string representation of a variable,
constant, or
$name = "Joel";
print, unlike echo, is an expression (it returns 1), and thus can be used in more places:
print ("hey" && (print (" " && print "you"))); #> you11
When outside of PHP tags, a shorthand notation for echo is available by default, using <?= to begin
output and ?> to
<p><?=$variable?></p>
Note that there is no terminating ;. This works because the closing PHP tag acts as the terminator for
the single
Priority of print
Although the print is language construction it has priority like operator. It places between = += -= *=
**= /= .= %=
print only takes one parameter, while echo can have multiple parameters.
objects
You may have a variable that is an array or object. Trying to output it with an echo will throw the
error:
Notice: Array to string conversion. You can instead use the print_r function to dump a human readable
You can pass true as the second parameter to return the content as a string.
$myint = 42;
print_r($myobject);
print_r($myarray);
print_r($mystring);
print_r($myint);
stdClass Object
(
[myvalue] => Hello World
Array
Hello World
42
Further, the output from print_r can be captured as a string, rather than simply echoed. For instance,
the following
code will dump the formatted version of $myarray into a new variable:
Note that if you are viewing the output of PHP in a browser, and it is interpreted as HTML, then the
line breaks will
not be shown and the output will be much less legible unless you do something like
Opening the source code of a page will also format your variable in the same way without the use of
the
<pre> tag.
Alternatively you can tell the browser that what you're outputting is plain text, and not HTML:
print_r($myarray);
value and other information like object IDs, array sizes, string lengths, reference markers, etc.
You can use var_dump to output a more detailed version for debugging.
object(stdClass)#12 (1) {
["myvalue"]=>
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
int(42)
Note: If you are using xDebug in your development environment, the output of var_dump is limited /
truncated by
default. See the official documentation for more info about the options to change this.
You can pass true as the second parameter to return the contents into a variable.
var_export($myarray);
var_export($mystring);
var_export($myint);
array (
0 => 'Hello',
1 => 'World',
'Hello World'
42
$myarray = array (
0 => 'Hello',
1 => 'World',
);
$myint = 42;
// String variable
$name = 'Joel';
// Concatenate multiple strings (3 in this example) into one and echo it once done.
// ↑ ↑ - Concatenation Operators
Similar to concatenation, echo (when used without parentheses) can be used to combine strings and
variables
$itemCount = 1;
echo 'You have ordered ', $itemCount, ' item', $itemCount === 1 ? '' : 's';
Passing multiple arguments to the echo command is more advantageous than string concatenation in
some
circumstances. The arguments are written to the output in the same order as they are passed in.
The problem with the concatenation is that the period . takes precedence in the expression. If
concatenated, the
above expression needs extra parentheses for the correct behavior. The precedence of the period
affects ternary
operators too.
$name = 'Jeff';
// ↓ `%s` is replaced by ↓
echo $greeting;
It is also possible to format a number with these 2 functions. This can be used to format a decimal
value used to
$money = 25.2;
printf('%01.2f', $money);
#> 25.20
The two functions vprintf and vsprintf operate as printf and sprintf, but accept a format string and an
array of
On 32-bits systems, integers larger than PHP_INT_MAX are automatically converted to float.
Outputting these as
integer values (i.e. non-scientific notation) can be done with printf, using the float representation, as
illustrated
below:
$i = pow(1024, $p);
printf("pow(1024, %d) > (%7s) %20s %38.0F", $p, gettype($i), $i, $i);
// outputs:
1.1258999068426E+15
1.1529215046068E+18
1.2379400392854E+27
1.3292279957849E+36
While this looks nice, in this contrived example the numbers can all be represented as a binary
number since they
are all powers of 1024 (and thus 2). See for example:
$n = pow(10, 27);
printf("%s %.0F\n", $n, $n);
// 1.0E+27 1000000000000000013287555072
Array
[id] => 13
[category_id] => 7
[virtual] => 1
[active] => 1
[sort_order] => 13
[id] => 16
[category_id] => 7
[virtual] => 1
[active] => 1
[sort_order] => 16
<table>
<?php
echo "<tr>";
echo "</tr>";
?>
</table>
Constants are created using the const statement or the define function. The convention is to use
UPPERCASE
if you have one constant you can define another one based on it:
const TAU = PI * 2;
define("EARTH_IS_ROUND", !EARTH_IS_FLAT);
define("MORE_UNKNOWN", UNKNOWN);
// the above example (a function call) does not work with const:
// const TIME = time(); # fails with a fatal error! Not a constant scalar expression
Reserved constants
Some constant names are reserved by PHP and cannot be redefined. All these examples will fail:
define("true", false); // internal constant
Conditional defines
If you have several files where you may define the same variable (for example, your main config then
your local
const vs define
Thus define allows for dynamic values (i.e. function calls, variables etc.) and even dynamic names and
conditional
const is static (as in allows only operations with other constants, scalars or arrays, and only a restricted
set of them,
the so called constant scalar expressions, i.e. arithmetic, logical and comparison operators as well as
array
dereferencing), but are automatically namespace prefixed with the currently active namespace.
const only supports other constants and scalars as values, and no operations.
class Foo {
return self::BAR_TYPE;
echo Foo::BAR_TYPE;
<?php
class Logger {
const LEVEL_INFO = 1;
const LEVEL_WARNING = 2;
const LEVEL_ERROR = 3;
Simple check
To check if constant is defined use the defined function. Note that this function doesn't care about
constant's
value, it only cares if the constant exists or not. Even if the value of the constant is null or false the
function will
<?php
define("GOOD", false);
if (defined("GOOD")) {
if (GOOD) {
print "GOOD is true" ; // does not print anything, since GOOD is false
if (!defined("AWESOME")) {
Note that constant becomes "visible" in your code only after the line where you have defined it:
<?php
if (defined("GOOD")) {
print "GOOD is defined"; // doesn't print anyhting, GOOD is not defined yet.
define("GOOD", false);
if (defined("GOOD")) {
To get all defined constants including those created by PHP use the get_defined_constants function:
<?php
$constants = get_defined_constants();
To get only those constants that were defined by your app call the function at the beginning and at the
end of your
<?php
$constants = get_defined_constants();
define("HELLO", "hello");
define("WORLD", "world");
$new_constants = get_defined_constants();
var_export($myconstants);
/*
Output:
array (
*/
if (EARTH_IS_FLAT) {
print "Earth is flat";
print APP_ENV_UPPERCASE;
or if you don't know the name of the constant in advance, use the constant function:
$const1 = "EARTH_IS_FLAT";
$const2 = "APP_ENV_UPPERCASE";
if (constant($const1)) {
print constant($const2);
Arrays can be used as plain constants and class constants from version PHP 5.6 onwards:
class Answer {
const C = [2,4];
Also from version PHP 7.0 this functionality was ported to the define function for plain constants.
define('MY_ARRAY', [
1,
VALUES,
]);
print MY_ARRAY[1][1]; // 3
__METHOD__
__FUNCTION__ returns only the name of the function whereas __METHOD__ returns the name of the
class along with
<?php
class trick
echo __FUNCTION__;
echo __METHOD__;
__CLASS__ magic constant returns the same result as get_class() function called without parameters
and they
both return the name of the class where it was defined (i.e. where you wrote the function
call/constant name ).
In contrast, get_class($this) and get_called_class() functions call, will both return the name of the
actual class
<?php
class Definition_Class {
$c = new Actual_Class();
$c->say();
// Output:
You can get the name of the current PHP file (with the absolute path) using the __FILE__ magic
constant. This is
Current directory
To get the absolute path to the directory where the current file is located use the __DIR__ magic
constant.
To get the absolute path to the directory where the current file is located, use dirname(__FILE__).
Getting current directory is often used by PHP frameworks to set a base directory:
$view = 'page';
Separators
Windows system perfectly understands the / in paths so the DIRECTORY_SEPARATOR is used mainly
when
parsing paths.
Besides magic constants PHP also adds some fixed constants for working with paths:
DIRECTORY_SEPARATOR constant for separating directories in a path. Takes value / on *nix, and \ on
Windows.
$view = 'page';
Windows, : otherwise
Chapter 8: Comments
The single line comment begins with "//" or "#". When encountered, all text to the right will be
ignored by the PHP
interpreter.
// This is a comment
echo "Hello World!"; // This is also a comment, beginning where we see "//"
The multi-line comment can be used to comment out large blocks of code. It begins with /* and ends
with */.
*/
Chapter 9: Types
There are two types of comparison: loose comparison with == and strict comparison with ===. Strict
comparison
ensures both the type and value of both sides of the operator are the same.
// Loose comparisons
// Strict comparisons
You can also use strong comparison to check if type and value don't match using !==.
A typical example where the == operator is not enough, are functions that can return different types,
like strpos,
which returns false if the searchword is not found, and the match position (int) otherwise:
This code sets the value of $foo as true and $bar as false:
$foo = true;
$bar = false;
true and false are not case sensitive, so TRUE and FALSE can be used as well, even FaLsE is possible.
Using lower
case is most common and recommended in most code style guides, e.g. PSR-2.
echo "true";
Due to the fact that PHP is weakly typed, if $foo above is other than true or false, it's automatically
coerced to a
boolean value.
To avoid this loose comparison, you can enforce strong comparison using ===, which compares value
and type. See
To convert a type into boolean, you can use the (bool) or (boolean) cast before the type.
$float = 0.123;
For historical reasons "double" is returned by gettype() in case of a float, and not simply "float"
Floats are floating point numbers, which allow more output precision than plain integers.
Floats and integers can be used together due to PHP's loose casting of variable types:
$sum = 3 + 0.14;
php does not show float as float number like other languages, for example:
$var = 1;
Warning
Floating point precision
Floating point numbers have limited precision. Although it depends on the system, PHP typically give a
maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic
operations
may give larger errors, and error propagation must be considered when several operations are
compounded.
Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like
0.1 or 0.7, do not have an exact representation as floating point numbers in base 2 (binary), which is
used
internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal
binary
counterparts without a small loss of precision. This can lead to confusing results: for example,
floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation
will be
So never trust floating number results to the last digit, and do not compare floating point numbers
directly for equality. If higher precision is necessary, the arbitrary precision math functions and gmp
A string in PHP is a series of single-byte characters (i.e. there is no native Unicode support) that can be
specified in
four ways:
Single Quoted
Displays things almost completely "as is". Variables and most escape sequences will not be
interpreted. The
exception is that to display a literal single quote, one can escape it with a back slash ', and to display a
back slash,
one can escape it with another backslash \
var_dump($my_string);
/*
*/
Double Quoted
Unlike a single-quoted string, simple variable names and escape sequences in the strings will be
evaluated. Curly
braces (as in the last example) can be used to isolate complex variable names.
$variable1 = "Testing!";
$my_string .= "$variable1\n\n$variable2[0]\n\n";
$my_string .= "But we can get around them by wrapping the whole variable in braces:
{$variable2[1][1]}";
var_dump($my_string);
/*
Testing!
Testing?
But we can get around them by wrapping the whole variable in braces: Success
*/
Heredoc
In a heredoc string, variable names and escape sequences are parsed in a similar manner to double-
quoted strings,
though braces are not available for complex variable names. The start of the string is delimited by
<<<identifier,
and the end by identifier, where identifier is any valid PHP name. The ending identifier must appear on
a line
by itself. No whitespace is allowed before or after the identifier, although like any line in PHP, it must
also be
terminated by a semicolon.
but there are advantages. $variable1; database queries and HTML output
Once we hit a line containing nothing but the identifier, the string ends.
EOF;
var_dump($my_string);
/*
but there are advantages. Including text blocks is easier; database queries and HTML output
Once we hit a line containing nothing but the identifier, the string ends."
*/
Nowdoc
A nowdoc string is like the single-quoted version of heredoc, although not even the most basic escape
sequences
are evaluated. The identifier at the beginning of the string is wrapped in single quotes.
nothing is parsed (not even escaped apostrophes \' and backslashes \\.)
EOF;
var_dump($my_string);
/*
string(116) "A similar syntax to heredoc but, similar to single quoted strings,
nothing is parsed (not even escaped apostrophes \' and backslashes \\.)"
*/
Callables are anything which can be called as a callback. Things that can be termed a "callback" are as
follows:
Anonymous functions
Static Classes
call_user_func([$obj, 'myCallbackMethod']);
$callable = function () {
return 'value';
};
call_user_func($fn);
call_something($callable);
A resource is a special type of variable that references an external resource, such as a file, socket,
stream,
document, or connection.
echo gettype($file);
# Out: resource
echo $file;
# Out: Resource id #2
There are different (sub-)types of resource. You can check the resource type using
get_resource_type():
echo get_resource_type($file);
#Out: stream
echo get_resource_type($sock);
#Out: stream
it is useful to manually force a type. This can be accomplished by prefixing the declaration with the
name of the
$bool = true;
var_dump($bool); // bool(true)
var_dump($int); // int(1)
var_dump($float); // float(1)
$object->x = 'y';
$string = "asdf";
var_dump((unset)$string); // NULL
But be careful: not all type casts work as one might expect:
PHP is a weakly-typed language. It does not require explicit declaration of data types. The context in
which the
$a = "2"; // string
$a = $a + 2; // integer (4)
PHP represents "no value" with the null keyword. It's somewhat similar to the null pointer in C-
language and to the
If the variable was not defined or was unset then any tests against the null will be successful but they
will also
$nullvar = null;
unset($nullvar);
Integers in PHP can be natively specified in base 2 (binary), base 8 (octal), base 10 (decimal), or base
16
(hexadecimal.)
$my_decimal = 42;
$my_binary = 0b101010;
$my_octal = 052;
$my_hexadecimal = 0x2a;
Integers are 32 or 64 bits long, depending on the platform. The constant PHP_INT_SIZE holds integer
size in bytes.
Integer values are automatically created as needed from floats, booleans, and strings. If an explicit
typecast is
GoalKicker.com – PHP Notes for Professionals 53
$my_numeric_string = "123";
var_dump($my_numeric_string);
$my_integer = (int)$my_numeric_string;
var_dump($my_integer);
// Output: int(123)
$too_big_integer = PHP_INT_MAX + 7;
var_dump($too_big_integer);
// Output: float(9.2233720368548E+18)
There is no integer division operator in PHP, but it can be simulated using an implicit cast, which
always 'rounds' by
just discarding the float-part. As of PHP version 7, an integer division function was added.
$not_an_integer = 25 / 4;
var_dump($not_an_integer);
// Output: float(6.25)
// Output: int(6)
// Output: int(6)
(Note that the extra parentheses around (25 / 4) are needed because the (int) cast has higher
precedence than
the division)
An operator is something that takes one or more values (or expressions, in programming jargon) and
yields
Null coalescing is a new operator introduced in PHP 7. This operator returns its first operand if it is set
and not
is equivalent to both:
if (isset($_POST['name'])) {
$name = $_POST['name'];
} else {
$name = 'nobody';
and:
if (isset($_GET['name'])) {
$name = $_GET['name'];
} elseif (isset($_POST['name'])) {
$name = $_POST['name'];
} else {
$name = 'nobody';
Note:
When using coalescing operator on string concatenation don't forget to use parentheses ()
$firstName = "John";
$lastName = "Doe";
This will output John only, and if its $firstName is null and $lastName is Doe it will output Unknown
Doe. In order to
$firstName = "John";
$lastName = "Doe";
PHP 7 introduces a new kind of operator, which can be used to compare expressions. This operator will
return -1, 0
or 1 if the first expression is less than, equal to, or greater than the second expression.
// Integers
// Floats
// Strings
Objects are not comparable, and so doing so will result in undefined behaviour.
This operator is particularly useful when writing a user-defined comparison function using usort,
uasort, or
uksort. Given an array of objects to be sorted by their weight property, for example, an anonymous
function can
});
The PHP execution operator consists of backticks (``) and is used to run shell commands. The output of
the
// List files
$output = `ls`;
echo "<pre>$output</pre>";
Note that the execute operator and shell_exec() will give the same result.
(--)
Variables can be incremented or decremented by 1 with ++ or --, respectively. They can either precede
or succeed
$i = 1;
More information about incrementing and decrementing operators can be found in the official
documentation.
The ternary operator can be thought of as an inline if statement. It consists of three parts. The
operator, and two
If the operator is evaluated as true, the value in the first block will be returned (<true value>), else the
value in the
second block will be returned (<false value>). Since we are setting $value to the result of our ternary
operator it
Example:
$action = empty($_POST['action']) ? 'default' : $_POST['action'];
$action would contain the string 'default' if empty($_POST['action']) evaluates to true. Otherwise it
would
The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1evaluates to true, and expr3 if
expr1
evaluates to false.
It is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns
expr1 if expr1
This behaves like the Null Coalescing operator ??, except that ?? requires the left operand to be exactly
null while
?: tries to resolve the left operand into a boolean and check if it resolves to boolean false.
Example:
In this example, setWidth accepts a width parameter, or default 0, to change the width session value.
If $width is 0
(if $width is not provided), which will resolve to boolean false, the value of getDefaultWidth() is used
instead. The
getDefaultWidth() function will not be called if $width did not resolve to boolean false.
Operator True if
$a or $b Either $a or $b is true
$a || $b Either $a or $b is true
Note that the && and || opererators have higher precedence than and and or. See table below:
Because of this it's safer to use && and || instead of and and or.
$a = "a";
$b = "b";
$a = "a";
Members of objects or classes can be accessed using the object operator (->) and the class operator
(::).
class MyClass {
public $a = 1;
public static $b = 2;
const C = 3;
var_dump($object->a); // int(1)
var_dump($object::$b); // int(2)
var_dump($object::C); // int(3)
var_dump(MyClass::$b); // int(2)
var_dump(MyClass::C); // int(3)
var_dump($object->d()); // int(4)
var_dump($object::d()); // int(4)
var_dump(MyClass::e()); // int(5)
$classname = "MyClass";
Note that after the object operator, the $ should not be written ($object->a instead of $object->$a).
For the class
operator, this is not the case and the $ is necessary. For a constant defined in the class, the $ is never
used.
Also note that var_dump(MyClass::d()); is only allowed if the function d() does not reference the
object:
class MyClass {
private $a = 1;
return $this->a;
var_dump(MyClass::d()); // Error!
This causes a 'PHP Fatal error: Uncaught Error: Using $this when not in object context'
These operators have left associativity, which can be used for 'chaining':
class MyClass {
private $a = 1;
$this->a += $a;
return $this;
return $this->a;
var_dump($object->add(4)->get()); // int(5)
These operators have the highest precedence (they are not even mentioned in the manual), even
higher that clone.
Thus:
class MyClass {
private $a = 0;
$this->a += $a;
return $this;
var_dump($o1->get()); // int(2)
var_dump($o2->get()); // int(2)
Note that using parentheses to influence precedence did not work in PHP version 5 and older (it does
in PHP 7):
The combined assignment operators are a shortcut for an operation on some variable and
subsequently assigning
Arithmetic:
$a = 1; // basic assignment
$a -= 1; // $a now is (3 - 1) => 2
$a *= 2; // $a now is (2 * 2) => 4
// array +
$arrOne = array(1);
$arrTwo = array(2);
$arrOne += $arrTwo;
$a = "a";
$a = 0b00101010; // $a now is 42
$a &= 0b00001111; // $a now is (00101010 & 00001111) => 00001010 (bitwise and)
parentheses)
The order in which operators are evaluated is determined by the operator precedence (see also the
Remarks
section).
In
$a = 2 * 3 + 4;
$a gets a value of 10 because 2 * 3 is evaluated first (multiplication has a higher precedence than
addition) yielding
a sub-result of 6 + 4, which equals to 10.
$a = 2 * (3 + 4);
$a = "some string";
The result of an assignment expression is the value being assigned. Note that a single equal sign = is
NOT for
comparison!
$a = 3;
$b = ($a = 5);
3. Line 2 then assigns the result of the expression in parentheses (5) to $b.
Left association
If the preceedence of two operators is equal, the associativity determines the grouping (see also the
Remarks
section):
* and % have equal precedence and left associativity. Because the multiplication occurs first (left), it is
grouped.
Right association
$a = 1;
$b = 1;
$a = $b += 1;
Both $a and $b now have value 2 because $b += 1 is grouped and then the result ($b is 2) is assigned
to $a.
Equality
For basic equality testing, the equal operator == is used. For more comprehensive checks, use the
identical operator
===.
The identical operator works the same as the equal operator, requiring its operands have the same
value, but also
For example, the sample below will display 'a and b are equal', but not 'a and b are identical'.
$a = 4;
$b = '4';
if ($a == $b) {
When using the equal operator, numeric strings are cast to integers.
Comparison of objects
=== compares two objects by checking if they are exactly the same instance. This means that new
stdClass() ===
new stdClass() resolves to false, even if they are created in the same way (and have the exactly same
values).
== compares two objects by recursively checking if they are equal (deep equals). That means, for $a ==
$b, if $a and
$b are:
3. for each property $property set, $a->property == $b->property is true (hence recursively checked).
They include:
1. Greater Than: $a > $b, returns true if $a's value is greater than of $b, otherwise returns false.
Example:
2. Lesser Than: $a < $b, returns true if $a's value is smaller that of $b, otherwise returns false.
Example:
3. Greater Than Or Equal To: $a >= $b, returns true if $a's value is either greater than of $b or equal to
$b,
Example:
4. Smaller Than Or Equal To: $a <= $b, returns true if $a's value is either smaller than of $b or equal to
$b,
Example:
5/6. Not Equal/Identical To: To rehash the earlier example on equality, the sample below will display 'a
and b are
$a = 4;
$b = '4';
if ($a != $b) {
Bitwise operators are like logical operators but executed per bit rather than per boolean value.
// bitwise NOT ~: sets all unset bits and unsets all set bits
Bitmask-bitmask operators
Bitwise XOR ^: a bit is set if it is set in one operand and not set in another operand, i.e. only if that bit
is in different
Here, the | operator is used to combine the two bitmasks. Although + has the same effect, |
emphasizes that you
class Foo{
const OPTION_A = 1;
const OPTION_B = 2;
const OPTION_C = 4;
const OPTION_A = 8;
$this->options ^= $option;
This example (assuming $option always only contain one bit) uses:
the | operator to set a bit neglecting its original state or other bits
the ~ operator to convert an integer with only one bit set into an integer with only one bit not set
Since &= with a set bit will not do anything ((1 & 1) === 1, (0 & 1) === 0), doing &= with an integer
with only one bit not set will only unset that bit, not affecting other bits.
&= with an unset bit will unset that bit ((1 & 0) === 0, (0 & 0) === 0)
Using the & operator with another bitmask will filter away all other bits not set in that bitmask.
If the output has any bits set, it means that any one of the options are enabled.
If the output has all bits of the bitmask set, it means that all of the options in the bitmask are enabled.
Bear in mind that these comparison operators: (< > <= >= == === != !== <> <=>) have higher precedence
than these
bitmask-bitmask operators: (| ^ &). As bitwise results are often compared using these comparison
operators, this is
Bit-shifting operators
Bitwise left shift <<: shift all bits to the left (more significant) by the given number of steps and discard
the bits
<< $x is equivalent to unsetting the highest $x bits and multiplying by the $xth power of 2
Bitwise right shift >>: discard the lowest shift and shift the remaining bits to the right (less significant)
>> $x is equivalent to dividing by the $xth power of 2 and discard the non-integer part
On 32-bit systems, this discards all bits in the integer, setting the value to 0. On 64-bit systems, this
unsets the most
Note: In this example, printf("%'06b") is used. It outputs the value in 6 binary digits.
For checking whether some object is of a certain class, the (binary) instanceof operator can be used
since PHP
version 5.
The first (left) parameter is the object to test. If this variable is not an object, instanceof always returns
false. If a
The second (right) parameter is the class to compare with. The class can be provided as the class name
itself, a
string variable containing the class name (not a string constant!) or an object of that class.
class MyClass {
$name = 'MyClass';
// counter examples:
$b = 'b';
instanceof can also be used to check whether an object is of some class which extends another class or
interface MyInterface {
$o = new MySubClass();
$a = $o instanceof MySubClass;
$a = $o instanceof MySuperClass;
$a = $o instanceof MyInterface;
To check whether an object is not of some class, the not operator (!) can be used:
class MyClass {
class OtherClass {
$o = new MyClass();
than !, although it may make the code better readable with parentheses.
Caveats
If a class does not exist, the registered autoload functions are called to try to define the class (this is a
topic outside
the scope of this part of the Documentation!). In PHP versions before 5.1.0, the instanceof operator
would also
trigger these calls, thus actually defining the class (and if the class could not be defined, a fatal error
would occur).
class MyClass {
$o = new MyClass();
// error occurs.
$name = 'YetAnotherClass';
As of PHP version 5.1.0, the registered autoloaders are not called anymore in these situations.
In older versions of PHP (before 5.0), the is_a function can be used to determine wether an object is of
some class.
This function was deprecated in PHP version 5 and undeprecated in PHP version 5.3.0.
This is the first phase of referencing. Essentially when you assign by reference, you're allowing two
variables to
$foo = &$bar;
$foo and $bar are equal here. They do not point to one another. They point to the same place (the
"value").
You can also assign by reference within the array() language construct. While not strictly being an
assignment by
reference.
$foo = 'hi';
Note, however, that references inside arrays are potentially dangerous. Doing a normal (not by
reference) assignment with a reference on the right side does not turn the left side into a reference,
but
references inside arrays are preserved in these normal assignments. This also applies to function calls
Assigning by reference is not only limited to variables and arrays, they are also present for functions
and all "passby-reference" associations.
function incrementArray(&$arr) {
$val++;
}
function &getArray() {
return $arr;
incrementArray(getArray());
Assignment is key within the function definition as above. You can not pass an expression by
reference, only a
Returning by reference is useful when you want to use a function to find to which variable a reference
should be bound. Do not use return-by-reference to increase performance. The engine will
automatically
optimize this on its own. Only return references when you have a valid technical reason to do so.
There are many different forms return by reference can take, including the following example:
function parent(&$var) {
echo $var;
$var = "updated";
function &child() {
static $a = "test";
return $a;
Return by reference is not only limited to function references. You also have the ability to implicitly
call the function:
function &myFunction() {
static $a = 'foo';
return $a;
$bar = &myFunction();
$bar = "updated"
echo myFunction();
You cannot directly reference a function call, it has to be assigned to a variable before harnessing it. To
see how that
Notes
You are required to specify a reference (&) in both places you intend on using it. That means, for your
function definition (function &myFunction() {...) and in the calling reference (function
You can only return a variable by reference. Hence the instantiation of $a in the example above. This
means
you can not return an expression, otherwise an E_NOTICE PHP error will be generated (Notice: Only
Return by reference does have legitimate use cases, but I should warn that they should be used
sparingly,
only after exploring all other potential options of achieving the same goal.
Section 11.3: Pass by Reference
This allows you to pass a variable by reference to a function or element that allows you to modify the
original
variable.
Passing-by-reference is not limited to variables only, the following can also be passed by reference:
Arrays
A common use of "passing-by-reference" is to modify initial values within an array without going to
the extent of
Below is an example of harnessing an element from an array and simply adding 1 to its initial value.
foreach($arr as &$num) {
$num++;
Now when you harness any element within $arr, the original element will be updated as the reference
was
print_r($arr);
Note
You should take note when harnessing pass by reference within loops. At the end of the above loop,
$num
still holds a reference to the last element of the array. Assigning it post loop will end up manipulating
the
last array element! You can ensure this doesn't happen by unset()'ing it post-loop:
foreach($myArray as &$num) {
$num++;
unset($num);
The above will ensure you don't run into any issues. An example of issues that could relate from this is
Functions
Another common usage for passing-by-reference is within functions. Modifying the original variable is
as simple as:
$var = 5;
// define
function add(&$var) {
$var++;
// call
add($var);
echo $var;
There are various restrictions around functions, as noted below from the PHP docs:
Note: There is no reference sign on a function call - only on function definitions. Function definitions
alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning
saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP
5.4.0,
call-time pass-by-reference was removed, so using it will raise a fatal error.
Parameter Detail
Key The key is the unique identifier and index of an array. It may be a string or an integer. Therefore,
Value For each key there is a corresponding value (null otherwise and a notice is emitted upon access).
The
An array is a data structure that stores an arbitrary number of values in a single value. An array in PHP
is actually an
// An empty array
$foo = array();
$foo = [];
An array can also be initialized with custom indexes (also called an associative array):
$fruit = array(
'first' => 'apples',
);
$fruit['first'] = 'apples';
$fruit = [
];
If the variable hasn't been used before, PHP will create it automatically. While convenient, this might
make the code
harder to read:
The index will usually continue where you left off. PHP will try to use numeric strings as integers:
$foo = [2 => 'apple', 'melon']; // Array( [2] => apple, [3] => melon )
$foo = [2 => 'apple', 'this is index 3 temporarily', '3' => 'melon']; // same as above! The last
$array[0] = 1;
$array[1] = 2;
$array[2] = 3;
$array[3] = 4; // RuntimeException
$array->setSize(10);
Note: An array created using SplFixedArray has a reduced memory footprint for large sets of data, but
the keys
must be integers.
To initialize an array with a dynamic size but with n non empty elements (e.g. a placeholder) you can
use a loop as
follows:
$myArray = array();
$sizeOfMyArray = 5;
$fill = 'placeholder';
$myArray[] = $fill;
// Array ( [0] => placeholder [1] => placeholder [2] => placeholder [3] => placeholder [4] =>
placeholder )
If all your placeholders are the same then you can also create it using the function array_fill():
This creates and returns an array with num entries of value, keys starting at start_index.
Note: If the start_index is negative it will start with the negative index and continue from 0 for the
following
elements.
$a = array_fill(5, 6, 'banana'); // Array ( [5] => banana, [6] => banana, ..., [10] => banana)
$b = array_fill(-2, 4, 'pear'); // Array ( [-2] => pear, [0] => pear, ..., [2] => pear)
Conclusion: With array_fill() you are more limited for what you can actually do. The loop is more
flexible and
Whenever you want an array filled with a range of numbers (e.g. 1-4) you could either append every
single element
This function creates an array containing a range of elements. The first two parameters are required,
where they
set the start and end points of the (inclusive) range. The third parameter is optional and defines the
size of the
steps being taken. Creating a range from 0 to 4 with a stepsize of 1, the resulting array would consist of
the
following elements: 0, 1, 2, 3, and 4. If the step size is increased to 2 (i.e. range(0, 4, 2)) then the
resulting array
$array = [];
$array[] = $i;
print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
print_r($array_with_range); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
range can work with integers, floats, booleans (which become casted to integers), and strings. Caution
should be
taken, however, when using floats as arguments due to the floating point precision problem.
$map = [
'foo' => 1,
];
isset($map['foo']); // true
!empty($map['foo']); // true
isset($map['bar']); // false
!empty($map['bar']); // false
Note that isset() treats a null valued element as non-existent. Whereas !empty() does the same for any
element
that equals false (using a weak comparision; for example, null, '' and 0 are all treated as false by !
empty()).
While isset($map['foobar']); is true, !empty($map['foobar']) is false. This can lead to mistakes (for
example,
it is easy to forget that the string '0' is treated as false) so use of !empty() is often frowned upon.
Note also that isset() and !empty() will work (and return false) if $map is not defined at all. This makes
them
Note that isset() has better performance than array_key_exists() as the latter is a function and the
former a
language construct.
$integer = 1337;
is_array($integer); // false
is_array($array); // true
You can type hint the array type in a function to enforce a parameter type; passing anything else will
result in a fatal
error.
$integer = 1337;
$email = 'hadibut@example.org';
This method is often used in frameworks to pass an array of variables between two components.
You can also use the function array_search() to get the key of a specific item in an array.
In PHP 5.5 and later you can use array_column() in conjunction with array_search().
$userdb = [
],
],
];
Another useful feature is accessing your custom object collections as arrays in PHP. There are two
interfaces
available in PHP (>=5.0.0) core to support this: ArrayAccess and Iterator. The former allows you to
access your
ArrayAccess
Assume we have a user class and a database table storing all the users. We would like to create a
UserCollection
2. perform basic (not all CRUD, but at least Create, Retrieve and Delete) operations on our users
collection
Consider the following source (hereinafter we're using short array creation syntax [] available since
version 5.4):
protected $_conn;
$connectionParams = [
];
[$username]
)->fetch();
return $ret;
}
// START of methods required by ArrayAccess interface
return $this->_getByUsername($offset);
if (!is_array($value)) {
throw new \Exception('value must contain at least the following params: ' .
implode(',', $this->_requiredParams));
$this->_conn->insert('User', $value);
if (!is_string($offset)) {
if (!$this->offsetGet($offset)) {
}
$this->_conn->delete('User', ['username' => $offset]);
then we can:
var_dump(empty($users['testuser']),isset($users['testuser']));
unset($users['testuser']);
var_dump(empty($users['testuser']), isset($users['testuser']));
which will output the following, assuming there was no testuser before we launched the code:
bool(true)
bool(false)
bool(false)
bool(true)
array(17) {
["username"]=>
string(8) "testuser"
["password"]=>
string(12) "testpassword"
["email"]=>
string(13) "test@test.com"
bool(true)
bool(false)
IMPORTANT: offsetExists is not called when you check existence of a key with array_key_exists
function. So the
var_dump(array_key_exists('testuser', $users));
var_dump(array_key_exists('testuser', $users));
Iterator
Let's extend our class from above with a few functions from Iterator interface to allow iterating over it
with
First, we need to add a property holding our current index of iterator, let's add it to the class
properties as
$_position:
protected $_position = 1;
Second, let's add Iterator interface to the list of interfaces being implemented by our class:
return $this->_getById($this->_position);
}
return $this->_position;
$this->_position++;
$this->_position = 1;
So all in all here is complete source of the class implementing both interfaces. Note that this example
is not perfect,
because the IDs in the database may not be sequential, but this was written just to give you the main
idea: you can
address your objects collections in any possible way by implementing ArrayAccess and Iterator
interfaces:
protected $_position = 1;
// <add the old methods from the last code snippet here>
// START of methods required by Iterator interface
return $this->_getById($this->_position);
return $this->_position;
$this->_position++;
$this->_position = 1;
var_dump($user['id']);
string(2) "1"
string(2) "2"
string(2) "3"
string(2) "4"
...
Sometimes two arrays of the same length need to be iterated together, for example:
array_map(function($person, $food) {
}, $people, $foods);
If the two arrays don't have the incremental keys, array_values($array)[$i] can be used to replace
$array[$i].
If both arrays have the same order of keys, you can also use a foreach-with-key loop on one of the
arrays:
foreach ($people as $index => $person) {
$food = $foods[$index];
Separate arrays can only be looped through if they are the same length and also have the same key
name. This
means if you don't supply a key and they are numbered, you will be fine, or if you name the keys and
put them in
// $combinedArray = ['Tim' => 'chicken', 'Tony' => 'beef', 'Turanga' => 'slurm'];
Then you can loop through this by doing the same as before:
This method works by incrementing an integer from 0 to the greatest index in the array.
This also allows iterating an array in reverse order without using array_reverse, which may result in
overhead if
You can skip or rewind the index easily using this method.
$array[$i] = "zeta";
$i -= 2;
$i++;
Output:
alpha
beta
gamma
beta
zeta
epsilon
For arrays that do not have incremental indices (including arrays with indices in reverse order, e.g. [1
=> "foo", 0
=> "bar"], ["foo" => "f", "bar" => "b"]), this cannot be done directly. array_values or array_keys can be
used instead:
$array = ["a" => "alpha", "b" => "beta", "c" => "gamma", "d" => "delta"];
$keys = array_keys($array);
$key = $keys[$i];
$value = $array[$key];
Each array instance contains an internal pointer. By manipulating this pointer, different elements of an
array can be
Using each
Each call to each() returns the key and value of the current array element, and increments the internal
array
pointer.
Using next
echo "$value\n";
Note that this example assumes no elements in the array are identical to boolean false. To prevent
such
assumption, use key to check if the internal pointer has reached the end of the array:
$array = ["Alpha", "Beta", "Gamma", "Delta"];
next($array);
class ColorPicker {
$result = next($colors);
reset($colors);
return $result;
Direct loop
Loop by reference
In the foreach loops in the above examples, modifying the value ($color or $food) directly doesn't
change its value
in the array. The & operator is required so that the value is a reference pointer to the element in the
array.
Concurrency
PHP arrays can be modified in any ways during iteration without concurrency problems (unlike e.g.
Java Lists). If
the array is iterated by reference, later iterations will be affected by changes to the array. Otherwise,
the changes to
the array will not affect later iterations (as if you are iterating a copy of the array instead). Compare
looping by
value:
if ($key === 0) {
$array[6] = 17;
unset($array[4]);
Output:
0 => 1
2 => 3
4 => 5
6 => 7
if ($key === 0) {
$array[6] = 17;
unset($array[4]);
Output:
0 => 1
2 => 3
6 => 17
The key-value set of 4 => 5 is no longer iterated, and 6 => 7 is changed to 6 => 17.
Php arrayiterator allows you to modify and unset the values while iterating over arrays and objects.
Example:
$array = ['1' => 'apple', '2' => 'banana', '3' => 'cherry'];
$iterator = $arrayObject->getIterator();
Output:
1 => apple
2 => banana
3 => cherry
To apply a function to every item in an array, use array_map(). This will return a new array.
$array = array(1,2,3,4,5);
//each array item is iterated over and gets stored in the function parameter.
$newArray = array_map(function($item) {
return $item + 1;
}, $array);
function addOne($item) {
return $item + 1;
If the named function is a class method the call of the function has to include a reference to a class
object the
class Example {
return $item + 1;
Another way to apply a function to every item in an array is array_walk() and array_walk_recursive().
The
callback passed into these functions take both the key/index and value of each array item. These
functions will not
return a new array, instead a boolean for success. For example, to print every element in a simple
array:
});
The value parameter of the callback may be passed by reference, allowing you to change the value
directly in the
original array:
$value++;
});
});
Note: array_walk and array_walk_recursive let you change the value of array items, but not the keys.
Passing the
Above code will make chunks of 2 array elements and create a multidimensional array as follow.
Array
[0] => a
[1] => b
[0] => c
[1] => d
[0] => e
If all the elements of the array is not evenly divided by the chunk size, last element of the output array
will be
remaining elements.
If we pass second argument as less then 1 then E_WARNING will be thrown and output array will be
NULL.
Parameter Details
$preserve_keys (boolean) (optional) If you want output array to preserve the keys set it to TRUE
otherwise FALSE.
implode() combines all the array values but looses all the key info:
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
Imploding keys with values is more complex but can be done using functional style:
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
}, array_keys($arr), $arr));
Use list() to quick assign a list of variable values into an array. See also compact()
// Assigns to $a, $b and $c the values of their respective array elements in $array with
With PHP 7.1 (currently in beta) you will be able to use short list syntax:
// Assigns to $a, $b and $c the values of their respective array elements in $array with keys
"c", respectively
["a" => $a, "b" => $b, "c" => $c] = $array;
array_reduce reduces array into a single value. Basically, The array_reduce will go through every item
with the
result from last iteration and produce new value to the next iteration.
Sum of array
});
result:15
});
result:211
result:true
Is any item less than 100
result:true
});
result:"hello-world-PHP-language"
});
result:"hello-world-PHP-language"
There are two ways to push an element to an array: array_push and $array[] =
$array = [1,2,3];
$newArraySize = array_push($array, 5, 6); // The method returns the new size of the array
Array
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
$array = [1,2,3];
$array[] = 5;
$array[] = 6;
print_r($array);
Array
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
In order to filter out values from an array and obtain a new array containing all the values that satisfy
the filter
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
Filtering by callback
This time we define our own filtering rule. Suppose we want to get only even numbers:
$my_array = [1,2,3,4,5,6,7,8];
});
The array_filter function receives the array to be filtered as its first argument, and a callback defining
the filter
Version ≥ 5.6
Filtering by index
A third parameter can be provided to the array_filter function, which allows to tweak which values are
passed to
result in the callback receiving the key instead of the value for each element in the array, or both value
and key as
its arguments. For example, if you want to deal with indexes istead of values:
$numbers = [16,3,5,8,1,4,6];
}, ARRAY_FILTER_USE_KEY);
Note that array_filter preserves the original array keys. A common mistake would be to try an use for
loop over
<?php
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
$filtered = array_filter($my_array);
print $filtered[$i];
/*
Output:
4
Notice: Undefined offset: 7
*/
This happens because the values which were on positions 1 (there was 0), 3 (null), 5 (empty string '')
and 7 (empty
array []) were removed along with their corresponding index keys.
If you need to loop through the result of a filter on an indexed array, you should first call array_values
on the
result of array_filter in order to create a new array with the correct indexes:
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
$filtered = array_filter($my_array);
$iterable = array_values($filtered);
print $iterable[$i];
// No warnings!
To remove an element inside an array, e.g. the element with the index 1.
unset($fruit[1]);
This will remove the apples from the list, but notice that unset does not change the indexes of the
remaining
print_r($fruit);
/*
Array
*/
unset($fruit['one']);
Now $fruit is
print_r($fruit);
/*
Array
*/
Note that
unset($fruit);
unsets the variable and thus removes the whole array, meaning none of its elements are accessible
anymore.
Example:
print_r($fruit);
Output:
Array
Example:
array_pop($fruit);
print_r($fruit);
Output:
Array
sort()
print_r($fruits);
results in
Array
rsort()
rsort($fruits);
print_r($fruits);
results in
Array
asort()
asort($fruits);
print_r($fruits);
results in
Array
arsort()
arsort($fruits);
print_r($fruits);
results in
Array
)
ksort()
ksort($fruits);
print_r($fruits);
results in
Array
krsort()
krsort($fruits);
print_r($fruits);
results in
Array
natsort()
natsort($files);
print_r($files);
results in
Array
natcasesort()
Sort an array in a way a human being would do (natural order), but case intensive
natcasesort($files);
print_r($files);
results in
Array
shuffle()
shuffle($array);
print_r($array);
As written in the description it is random so here only one example in what it can result
Array
[0] => cc
[1] => bb
[2] => aa
usort()
if ($a == $b) {
return 0;
usort($array, 'compare');
print_r($array);
results in
Array
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
uasort()
Sort an array with a user defined comparison function and preserve the keys.
if ($a == $b) {
return 0;
$array = ['a' => 1, 'b' => -3, 'c' => 5, 'd' => 3, 'e' => -5];
uasort($array, 'compare');
print_r($array);
results in
Array
[e] => -5
[b] => -3
[a] => 1
[d] => 3
[c] => 5
uksort()
if ($a == $b) {
return 0;
$array = ['ee' => 1, 'g' => -3, '4' => 5, 'k' => 3, 'oo' => -5];
uksort($array, 'compare');
print_r($array);
results in
Array
(
[ee] => 1
[g] => -3
[k] => 3
[oo] => -5
[4] => 5
When you want to allow only certain keys in your arrays, especially when the array comes from
request parameters,
$parameters = ['foo' => 'bar', 'bar' => 'baz', 'boo' => 'bam'];
If the parameters variable doesn't contain any allowed key, then the filteredParameters variable will
consist of an
empty array.
Since PHP 5.6 you can use array_filter for this task too, passing the ARRAY_FILTER_USE_KEY flag as the
third
parameter:
$filteredParameters = array_filter(
$parameters,
ARRAY_FILTER_USE_KEY
);
Using array_filter gives the additional flexibility of performing an arbitrary test against the key, e.g.
$allowedKeys
could contain regex patterns instead of plain strings. It also more explicitly states the intention of the
code than
Sometimes you want to add an element to the beginning of an array without modifying any of the
current
elements (order) within the array. Whenever this is the case, you can use array_unshift().
array_unshift() prepends passed elements to the front of the array. Note that the list of elements is
prepended as a whole, so that the prepended elements stay in the same order. All numerical array
keys
will be modified to start counting from zero while literal keys won't be touched.
array_unshift($myArray, 4);
This will now add 4 as the first element in your array. You can verify this by:
print_r($myArray);
Since array_unshift forces the array to reset the key-value pairs as the new element let the following
entries have
the keys n+1 it is smarter to create a new array and append the existing array to the newly created
array.
Example:
$myElement = array('oranges');
$joinedArray = $myElement;
$joinedArray[] = $i;
Output ($joinedArray):
Array ( [0] => oranges [1] => apples [2] => bananas [3] => pears )
Eaxmple/Demo
$colors = array(
);
array(
$a1 = array("red","green");
$a2 = array("blue","yellow");
print_r(array_merge($a1,$a2));
/*
Array ( [0] => red [1] => green [2] => blue [3] => yellow )
*/
Associative array:
$a1=array("a"=>"red","b"=>"green");
$a2=array("c"=>"blue","b"=>"yellow");
print_r(array_merge($a1,$a2));
/*
Array ( [a] => red [b] => yellow [c] => blue )
*/
1. Merges the elements of one or more arrays together so that the values of one are appended to the
end of
2. If the input arrays have the same string keys, then the later value for that key will overwrite the
previous one.
If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but
will be
appended.
3. Values in the input array with numeric keys will be renumbered with incrementing keys starting
from zero in
Together
Section 16.1: Array intersection
The array_intersect function will return an array of values that exist in all arrays that were passed to
this function.
Array keys are preserved. Indexes from the original arrays are not.
array_intersect only check the values of the arrays. array_intersect_assoc function will return
intersection of
array_intersect_key function only check the intersection of keys. It will returns keys exist in all arrays.
// now value of $all_of_fruits is [0 => 'apples', 1 => 'pears', 2 => 'bananas', 3 => 'oranges']
Note that array_merge will change numeric indexes, but overwrite string indexes
array_merge overwrites the values of the first array with the values of the second array, if it cannot
renumber the
index.
You can use the + operator to merge two arrays in a way that the values of the first array never get
overwritten, but
it does not renumber numeric indexes, so you lose values of arrays that have an index that is also used
in the first
array.
array
['foo', 'bar'],
['fizz', 'buzz'],
$multidimensionalArray = [
['foo', 'bar'],
['fizz', 'buzz'],
];
Or, you can skip setting $associativeArrayKeys and $associativeArrayValues and use this simple one
liner:
array_column($multidimensionalArray, 1));
from another)
The following example shows how to merge two arrays into one associative array, where the key
values will be the
items of the first array, and the values will be from the second:
$array_one = ['key1', 'key2', 'key3'];
var_export($array_three);
/*
array (
*/
\DateTimeImmutable::createFromMutable($concrete);
\DateTimeImmutable::createFromFormat(\DateTime::ISO8601, $mutable->format(\
DateTime::ISO8601),
$mutable->getTimezone());
We can use the class DateInterval to add or subtract some interval in a DateTime object.
See the example below, where we are adding an interval of 7 days and printing a message on the
screen:
$now = new DateTime();// empty argument returns the current date
String
$now->sub($interval);
echo "Samara says: Seven Days. You were happy last on $formatedLastDay.";
echo $date->getTimestamp();
this will out put an integer indication the seconds that have elapsed since 00:00:00 UTC, Thursday, 1
January 1970.
$date->setDate(2016, 7, 25);
this example sets the date to be the twenty-fifth of July, 2015, it will produce the following result:
2016-07-25 17:52:15.819442
PHP is able to parse a number of date formats. If you want to parse a non-standard format, or if you
want your
code to explicitly state the format to be used, then you can use the static
DateTime::createFromFormat method:
$format = "Y,m,d";
$time = "2009,2,26";
Procedural style
$format = "Y,m,d";
$time = "2009,2,26";
PHP 4+ supplies a method, format that converts a DateTime object into a string with a desired format.
According to
Format
The format is a string, and uses single characters to define the format:
A: either AM or PM
Usage
These characters can be used in various combinations to display times in virtually any format. Here are
some
examples:
$date->format("H:i");
/* Returns 13:30 */
$date->format("H i s");
/* Returns 13 30 20 */
$date->format("h:i:s A");
/* Returns 01:30:20 PM */
$date->format("j/m/Y");
/* Returns 26/05/2000 */
Procedural
Object-Oriented
$date->format($format)
Procedural Equivalent
date_format($date, $format)
An example:
<?php
// Create a date time object, which has the value of ~ two years ago
$diff = $now->diff($twoYearsAgo);
$yearsDiff = $diff->y;
$monthsDiff = $diff->m;
$daysDiff = $diff->d;
$hoursDiff = $diff->h;
$minsDiff = $diff->i;
// $diff->s contains the difference in seconds between the two dates
$secondsDiff = $diff->s;
// Total Days Diff, that is the number of days between the two dates
$totalDaysDiff = $diff->days;
var_dump($diff);
Also, comparing two dates is much easier, just use the Comparison operators , like:
<?php
// Create a date time object, which has the value of ~ two years ago
The Basics
The simplist way to convert one date format into another is to use strtotime() with date(). strtotime()
will
convert the date into a Unix Timestamp. That Unix Timestamp can then be passed to date() to convert
it to the
new format.
$timestamp = strtotime('2008-07-01T22:35:17.02');
Keep in mind that strtotime() requires the date to be in a valid format. Failure to provide a valid
format will result
Using DateTime()
As of PHP 5.2, PHP offered the DateTime() class which offers us more powerful tools for working with
dates (and
date() takes a Unix timestamp as its second parameter and returns a formatted date for you:
If the timestamp you have is in milliseconds (it may end in 000 and/or the timestamp is thirteen
characters long)
you will need to convert it to seconds before you can can convert it to another format. There's two
ways to do this:
Trimming the last three digits can be achieved several ways, but using substr() is the easiest:
You can also convert the timestamp into seconds by dividing by 1000. Because the timestamp is too
large for 32 bit
systems to do math on you will need to use the BCMath library to do the math as strings:
To get a Unix Timestamp you can use strtotime() which returns a Unix Timestamp:
$timestamp = strtotime('1973-04-18');
$timestamp = $date->getTimestamp();
If you're running PHP 5.2 you can use the U formatting option instead:
$timestamp = $date->format('U');
Unfortunately not all dates that a developer has to work with are in a standard format. Fortunately
PHP 5.3
provided us with a solution for that. DateTime::createFromFormat() allows us to tell PHP what format
a date string
In PHP 5.4 we gained the ability to do class member access on instantiation has been added which
allows us to turn
format
Using the strtotime() function combined with date() you can parse different English text descriptions
to dates:
echo date("m/d/Y", strtotime("10 September 2000")), "\n"; // prints September 10, 2000 in the
m/d/Y
format
echo date("m/d/Y", strtotime("+1 week")), "\n"; // prints the result of the current date + a week
echo date("m/d/Y", strtotime("+1 week 2 days 4 hours 2 seconds")), "\n"; // same as the last
echo date("m/d/Y", strtotime("First day of next month")), "\n"; // prints date of first day of next
month
echo date("m/d/Y", strtotime("Last day of next month")), "\n"; // prints date of last day of next
month
echo date("m/d/Y", strtotime("First day of last month")), "\n"; // prints date of first day of last
month
echo date("m/d/Y", strtotime("Last day of last month")), "\n"; // prints date of last day of last
month
We can use Predefined Constants for Date format in date() instead of the conventional date format
strings since
PHP 5.1.0.
Usage Examples
echo date(DATE_RFC822);
echo date(DATE_ATOM,mktime(0,0,0,8,15,1947));
The if statement in the example above allows to execute a code fragment, when the condition is met.
When you
want to execute a code fragment, when the condition is not met you extend the if with an else.
} else {
The ternary operator evaluates something based on a condition being true or not. It is a comparison
operator and
often used to express a simple if-else condition in a shorter form. It allows to quickly test a condition
and often
This is the example from above using a ternary expression and variable values: $a=1; $b=2;
echo ($a > $b) ? "a is greater than b" : "a is NOT greater than b";
PHP provides an alternative syntax for some control structures: if, while, for, foreach, and switch.
When compared to the normal syntax, the difference is, that the opening brace is replaced by a colon
(:) and the
closing brace is replaced by endif;, endwhile;, endfor;, endforeach;, or endswitch;, respectively. For
individual
if ($a == 42):
endif;
if ($a == 5):
else:
echo "a is neither 5 nor 6";
endif;
while loop iterates through a block of code as long as a specified condition is true.
$i = 1;
echo $i;
$i++;
Output:
123456789
do-while loop first executes a block of code once, in every case, then iterates through that block of
code as long as
$i = 0;
do {
$i++;
echo $i;
Output: `12345678910`
The goto instruction is a goto followed by the desired target label: goto MyLabel;.
<?php
goto MyLabel;
MyLabel:
?>
ticks
encoding
strict_types
declare(ticks=1);
To enable strict type mode, the declare statement is used with the strict_types declaration:
declare(strict_types=1);
require
require is similar to include, except that it will produce a fatal E_COMPILE_ERROR level error on
failure. When the
require fails, it will halt the script. When the include fails, it will not halt the script and only emit
E_WARNING.
require 'file.php';
include
./variables.php
$a = 'Hello World!';
./main.php`
include 'variables.php';
echo $a;
Be careful with this approach, since it is considered a code smell, because the included file is altering
amount and
You can also include file, which returns a value. This is extremely useful for handling configuration
arrays:
configuration.php
<?php
return [
];
main.php
<?php
This approach will prevent the included file from polluting your current scope with changed or added
variables.
include & require can also be used to assign values to a variable when returned something by file.
Example :
include1.php file :
<?php
$a = "This is to be returned";
return $a;
?>
index.php file :
The return statement returns the program control to the calling function.
When return is called from within a function, the execution of the current function will end.
function returnEndsFunctions()
return;
When you run returnEndsFunctions(); you'll get the output This is executed;
When return is called from within a function with and argument, the execution of the current function
will end and
the value of the argument will be returned to the calling function.
for loops are typically used when you have a piece of code which you want to repeat a given number
of times.
echo $i;
Outputs:
123456789
foreach is a construct, which enables you to iterate over arrays and objects easily.
echo $value;
Outputs:
123
$array = ['color'=>'red'];
}
Outputs:
color: red
elseif
elseif combines if and else. The if statement is extended to execute a different statement in case the
original if
expression is not met. But, the alternative expression is only executed, when the elseif conditional
expression is
met.
The following code displays either "a is bigger than b", "a is equal to b" or "a is smaller than b":
} else {
You can use multiple elseif statements within the same if statement:
if ($a == 1) {
} elseif ($a == 2) {
} elseif ($a == 3) {
echo "a is Three";
} else {
Section 19.12: if
The switch structure performs the same function as a series of if statements, but can do the job in
fewer lines of
code. The value to be tested, as defined in the switch statement, is compared for equality with the
values in each of
the case statements until a match is found and the code in that block is executed. If no matching case
statement is
Each block of code in a case or default statement should end with the break statement. This stops the
execution
of the switch structure and continues code execution immediately afterwards. If the break statement
is omitted,
the next case statement's code is executed, even if there is no match. This can cause unexpected code
execution if
the break statement is forgotten, but can also be useful where multiple case statements need to share
the same
code.
switch ($colour) {
case "red":
break;
case "green":
case "blue":
break;
case "yellow":
case "black":
break;
default:
break;
In addition to testing fixed values, the construct can also be coerced to test dynamic statements by
providing a
boolean value to the switch statement and any expression to the case statement. Keep in mind the
first matching
value is used, so the following code will output "more than 100":
$i = 1048;
switch (true) {
break;
break;
For possible issues with loose typing while using the switch construct, see Switch Surprises
Loops are a fundamental aspect of programming. They allow programmers to create code that repeats
for some
given number of repetitions, or iterations. The number of iterations can be explicit (6 iterations, for
example), or
This topic covers the different types of loops, their associated control statements, and their potential
applications in
PHP.
The continue keyword halts the current iteration of a loop but does not terminate the loop.
Just like the break statement the continue statement is situated inside the loop body. When executed,
the
In the following example loop prints out a message based on the values in an array, but skips a
specified value.
$list = ['apple', 'banana', 'cherry'];
if ($value == 'banana') {
continue;
The continue statement may also be used to immediately continue execution to an outer level of a
loop by
specifying the number of loop levels to jump. For example, consider data such as
Apple Red 1
Banana Yellow 7
Cherry Red 2
Grape Green 4
In order to only make pies from fruit which cost less than 5
$data = [
];
foreach($data as $fruit) {
foreach($fruit as $key => $value) {
continue 2;
/* make a pie */
When the continue 2 statement is executed, execution immediately jumps back to $data as $fruit
continuing
the outer loop and skipping all other code (including the conditional in the inner loop.
Similar to the continue statement, a break halts execution of a loop. Unlike a continue statement,
however, break
causes the immediate termination of the loop and does not execute the conditional statement again.
$i = 5;
while(true) {
echo 120/$i.PHP_EOL;
$i -= 1;
if ($i == 0) {
break;
24
30
40
60
120
but will not execute the case where $i is 0, which would result in a fatal error due to division by 0.
The break statement may also be used to break out of several levels of loops. Such behavior is very
useful when
executing nested loops. For example, to copy an array of strings into an output string, removing any #
symbols,
$output = "";
$inputs = array(
"#soblessed #throwbackthursday",
"happy tuesday",
"#nofilter",
/* more inputs */
);
foreach($inputs as $input) {
$output .= $input[$i];
The break 2 command immediately terminates execution of both the inner and outer loops.
GoalKicker.com – PHP Notes for Professionals 118
For each iteration the value of the current array element is assigned to $value variable and the array
pointer is
moved by one and in the next iteration next element will be processed.
You can also access the key / index of a value using foreach:
By default $value is a copy of the value in $list, so changes made inside the loop will not be reflected
in $list
afterwards.
To modify the array within the foreach loop, use the & operator to assign $value by reference. It's
important to
unset the variable afterwards so that reusing $value elsewhere doesn't overwrite the array.
unset($value);
You can also modify the array items within the foreach loop by referencing the array key of the current
item.
The do...while statement will execute a block of code at least once - it then will repeat the loop as long
as a condition is true.
The following example will increment the value of $i at least once, and it will continue incrementing
the variable $i
$i = 0;
do {
$i++;
The for statement is used when you know how many times you want to execute a statement or a block
of statements.
The initializer is used to set the start value for the counter of the number of loop iterations. A variable
may be
# Example 2
if ($i > 9) {
break;
# Example 3
$i = 0;
for (; ; ) {
if ($i > 9) {
break;
$i++;
}
# Example 4
0,1,2,3,4,5,6,7,8,9,
The while statement will execute a block of code if and as long as a test expression is true.
If the test expression is true then the code block will be executed. After the code has executed the test
expression
will again be evaluated and the loop will continue until the test expression is found to be false.
The following example iterates till the sum reaches 100 before terminating.
$i = true;
$sum = 0;
while ($i) {
$i = false;
} else {
$sum += 10;
PHP 5.6 introduced variable-length argument lists (a.k.a. varargs, variadic arguments), using the ...
token before
the argument name to indicate that the parameter is variadic, i.e. it is an array including all supplied
parameters
echo json_encode($variadic);
The & reference operator can be added before the ..., but after the type name (if any). Consider this
example:
class Foo{}
$i = 0;
$foo = $i++;
$a = new Foo;
$c = new Foo;
$b =& $c;
a($a, $b);
Output:
int(0)
int(1)
int(1)
On the other hand, an array (or Traversable) of arguments can be unpacked to be passed to a function
in the form
of an argument list:
var_dump(...hash_algos());
Output:
string(3) "md2"
string(3) "md4"
string(3) "md5"
...
var_dump(hash_algos());
Output:
array(46) {
[0]=>
string(3) "md2"
[1]=>
string(3) "md4"
...
Therefore, redirect functions for variadic functions can now be easily made, for example:
Apart from arrays, Traversables, such as Iterator (especially many of its subclasses from SPL) can also
be used.
For example:
var_dump(...$iterator);
In PHP 5.6:
A fatal error of memory exhaustion ("Allowed memory size of %d bytes exhausted") will be shown.
Note: HHVM (v3.10 - v3.12) does not support unpacking Traversables. A warning message "Only
switch ($style) {
case 'Formal':
break;
case 'Informal':
break;
case 'Australian':
break;
default:
break;
hello('Alice');
hello('Alice', 'Australian');
// G'day Alice
Function arguments can be passed "By Reference", allowing the function to modify the variable used
outside the
function:
function pluralize(&$word)
} else {
$word .= 's';
}
$word = 'Bannana';
pluralize($word);
print $word;
// Bannanas
function addOneDay($date)
$date->modify('+1 day');
addOneDay($date);
print $date->format('Y-m-d');
// 2014-03-01
To avoid implicit passing an object by reference, you should clone the object.
Passing by reference can also be used as an alternative way to return parameters. For example, the
socket_getpeername function:
This method actually aims to return the address and port of the peer, but since there are two values to
return, it
}
echo "Peer: $address:$port\n";
The variables $address and $port do not need to be defined before. They will:
function hello($name)
hello("Alice");
$number = 5
function foo(){
$number = 10
return $number
foo(); //Will print 10 because text defined inside function is a local variable
PHP's functional programming relies on functions. Functions in PHP provide organized, reusable code
to perform a
set of actions. Functions simplify the coding process, prevent redundant logic, and make code easier to
follow. This
topic describes the declaration and utilization of functions, arguments, parameters, return statements
and scope in
PHP.
When defining an anonymous function as such, you're creating a "namespace" for that function. It
currently only
$externalVariable = "Hello";
$secondExternalVariable = "Foo";
$myFunction = function() {
It doesn't have access to any external variables. To grant this permission for this namespace to access
external
This is heavily attributed to PHP's tight variable scoping - If a variable isn't defined within the scope, or
isn't brought in
Also note:
Inheriting variables from the parent scope is not the same as using global variables. Global variables
exist
in the global scope, which is the same no matter what function is executing.
The parent scope of a closure is the function in which the closure was declared (not necessarily the
In PHP, closures use an early-binding approach. This means that variables passed to the closure's
namespace
using use keyword will have the same values when the closure was defined.
$rate = .05;
};
$rate = .1;
print $calculateTax(100); // 5
$rate = .05;
$calculateTax = function ($value) use (&$rate) { // notice the & before $rate
};
$rate = .1;
print $calculateTax(100); // 10
Default arguments are not implicitly required when defining anonymous functions with/without
closures.
echo strtoupper($message);
};
Anonymous functions can be assigned to variables for use as parameters where a callback is expected:
$uppercase = function($data) {
return strtoupper($data);
};
print_r($uppercased);
class SomeClass {
An object with an __invoke method can be used exactly as any other function.
The __invoke method will have access to all properties of the object and will be able to call any
methods.
The use construct is used to import variables into the anonymous function's scope:
$divisor = 2332;
};
$collection = [];
$collection[] = $item;
};
$additem(1);
$additem(2);
// Anonymous function
function() {
};
In PHP, an anonymous function is treated like an expression and for this reason, it should be ended
with a
semicolon ;.
};
$users = [
];
$userName = array_map(function($user) {
return $user['name'];
}, $users);
(function () {
})();
call_user_func(function () {
(function ($name) {
})('John');
call_user_func(function ($name) {
}, 'John');
A pure function is a function that, given the same input, will always return the same output and are
side-effect
free.
return $a + $b;
Some side-effects are changing the filesystem, interacting with databases, printing to the screen.
echo "Adding...";
return $a + $b;
Mapping
Applying a function to all elements of an array:
array_map('strtoupper', $array);
Be aware that this is the only method of the list where the callback comes first.
});
Filtering
Returns only the array items for which the callback returns true:
});
In functions taking callable as an argument, you can also put a string with PHP built-in function. It's
common to
use trim as array_map parameter to remove leading and trailing whitespace from all strings in the
array.
var_dump(array_map('trim', $arr));
// array(3) {
// [0] =>
// string(3) "one"
// [1] =>
// string(3) "two"
// [2] =>
// string(5) "three"
// }
In PHP, an anonymous function has its own scope like any other PHP function.
In JavaScript, an anonymous function can access a variable in outside scope. But in PHP, this is not
permitted.
$name = 'John';
$sayHello = function() {
There are several PHP functions that accept user-defined callback functions as a parameter, such as:
Depending on where the user-defined callback function was defined there are different ways to pass
them:
Procedural style:
function square($number)
class SquareHolder
function square($number)
class StaticSquareHolder
// or:
$final_array = array_map('StaticSquareHolder::square', $initial_array); // for PHP >= 5.2.3
Structures
<?php
if ($condition):
do_something();
elseif ($another_condition):
do_something_else();
else:
do_something_different();
endif;
?>
<?php
endfor;
?>
<?php
while ($condition):
do_something();
endwhile;
?>
<?php
do_something($item);
endforeach;
?>
<?php
switch ($condition):
case $value:
do_something();
break;
default:
do_something_else();
break;
endswitch;
?>
<?php case $value: /* having whitespace before your cases will cause an error */ ?>
You can also use interpolation to interpolate (insert) a variable within a string. Interpolation works in
double quoted
$name = 'Joel';
// $name will be replaced with `Joel`
#↕
// Single Quotes: outputs $name as the raw text (without interpreting it)
echo 'Hello $name, Nice to see you.'; # Careful with this notation
The complex (curly) syntax format provides another option which requires that you wrap your variable
within
curly braces {}. This can be useful when embedding variables within textual content and helping to
prevent
$name = 'Joel';
// Example using the curly brace syntax for the variable $name
The {} syntax only interpolates variables starting with a $ into a string. The {} syntax does not evaluate
arbitrary
PHP expressions.
function say_hello() {
return "Hello!";
};
However, the {} syntax does evaluate any array access, property access and function/method calls on
variables,
$companions = [0 => ['name' => 'Amy Pond'], 1 => ['name' => 'Dave Random']];
class Person {
function say_hello() {
return "Hello!";
// Example of invoking a Closure — the parameter list allows for custom expressions
$greet = function($num) {
};
Notice that the dollar $ sign can appear after the opening curly brace { as the above examples, or, like
in Perl or
$name = 'Joel';
// Example using the curly brace syntax with dollar sign before the opening curly brace
The Complex (curly) syntax is not called as such because it's complex, but rather because it allows for
the use of 'complex expressions'. Read more about Complex (curly) syntax
Single characters can be extracted using array (square brace) syntax as well as curly brace syntax.
These two
syntaxes will only return a single character from the string. If more than one character is needed, a
function will be
Strings can also be changed one character at a time using the same square brace and curly brace
syntax. Replacing
// note that the replacement string need not be the same length as the substring replaced
A string containing several parts of text that are separated by a common character can be split into
parts with the
explode function.
$fruits = "apple,pear,grapefruit,cherry";
The method also supports a limit parameter that can be used as follow:
$fruits= 'apple,pear,grapefruit,cherry';
print_r(explode(',',$fruits,0)); // ['apple,pear,grapefruit,cherry']
If limit is set and positive, the returned array will contain a maximum of limit elements with the last
element
explode can be combined with list to parse a string into variables in one line:
$email = "user@example.com";
However, make sure that the result of explode contains enough elements, or an undefined index
warning would be
triggered.
strstr strips away or only returns the substring before the first occurrence of the given needle.
$string = "1:23:456";
Substring returns the portion of string specified by the start and length parameters.
If there is a possibility of meeting multi-byte character strings, then it would be safer to use
mb_substr.
$cake = "cakeæøå";
Another variant is the substr_replace function, which replaces text within a portion of a string.
Let's say you want to find a specific word in a string - and don't want to use Regex.
$hi = "Hello World!";
// If the casing in the text is not important, then using strtolower helps to compare strings
$email = "test@example.com";
$wrong = "foobar.co.uk";
$notld = "foo@bar";
$limit = 20;
strpos can be understood as the number of bytes in the haystack before the first occurrence of the
needle.
Be careful with checking against TRUE or FALSE because if a index of 0 is returned an if statement will
see this as
FALSE.
else {
else {
else {
}
Output of the whole example:
$needle = "Hello";
$offsets = [];
for($offset = 0;
// as 1 or 2 "aa"s.
$offset = $pos + 1;
preg_match can be used to parse string using regular expression. The parts of expression enclosed in
parenthesis
are called subpatterns and with them you can pick individual parts of the string.
if($result === 1) {
print_r($matches);
// No match
} else {
// Error occurred
Output
Array
Classes and Objects are used to to make your code more efficient and less repetitive by grouping
similar tasks.
A class is used to define the actions and data structure used to build objects. The objects are then built
using this
predefined structure.
Class constants provide a mechanism for holding fixed values in a program. That is, they provide a way
of giving a
name (and associated compile-time checking) to a value like 3.14 or "Apple". Class constants can only
be defined
with the const keyword - the define function cannot be used in this context.
As an example, it may be convenient to have a shorthand representation for the value of π throughout
a program.
A class with const values provides a simple way to hold such values.
class MathValues {
const PI = M_PI;
Class constants may be accessed by using the double colon operator (so-called the scope resolution
operator) on a
class, much like static variables. Unlike static variables, however, class constants have their values
fixed at compile
time and cannot be reassigned to (e.g. MathValues::PI = 7 would produce a fatal error).
Class constants are also useful for defining things internal to a class that might need changing later
(but do not
change frequently enough to warrant storing in, say, a database). We can reference this internally
using the self
class Labor {
Class constants can only contain scalar values in versions < 5.6
As of PHP 5.6 we can use expressions with constants, meaning math statements and strings with
concatenation are
acceptable constants
class Labor {
/** How much are we paying employees per hour? Hourly wages * hours taken to make */
define("BAZ", array('baz'));
Class constants are useful for more than just storing mathematical concepts. For example, if preparing
a pie, it
might be convenient to have a single Pie class capable of taking different kinds of fruit.
class Pie {
protected $fruit;
$this->fruit = $fruit;
The problem that arises here is, when instantiating the Pie class, no guidance is provided as to the
acceptable
values. For example, when making a "boysenberry" pie, it might be misspelled "boisenberry".
Furthermore, we
might not support a plum pie. Instead, it would be useful to have a list of acceptable fruit types
already defined
somewhere it would make sense to look for them. Say a class named Fruit:
class Fruit {
Listing the acceptable values as class constants provides a valuable hint as to the acceptable values
which a method
accepts. It also ensures that misspellings cannot make it past the compiler. While new Pie('aple') and
new
Pie('apple') are both acceptable to the compiler, new Pie(Fruit::APLE) will produce a compiler error.
Finally, using class constants means that the actual value of the constant may be modified in a single
place, and any
code using the constant automatically has the effects of the modification.
Whilst the most common method to access a class constant is MyClass::CONSTANT_NAME, it may also
be accessed
by:
echo MyClass::CONSTANT;
$classname = "MyClass";
Class constants in PHP are conventionally named all in uppercase with underscores as word
separators, although
As of PHP 7.1, class constants may now be defined with different visibilities from the default public
scope. This
means that both protected and private constants can now be defined to prevent class constants from
unnecessarily
leaking into the public scope (see Method and Property Visibility ). For example:
class Something {
const PUBLIC_CONST_A = 1;
}
define vs class constants
define('BAR', bar());
If you try to do the same with class constants, you'll get an error:
class Foo {
define('BAR', bar());
class Foo {
PHP 5.5 introduced the ::class syntax to retrieve the full class name, taking namespace scope and use
statements
into account.
namespace foo;
use bar\Bar;
The above works even if the classes are not even defined (i.e. this code snippet works alone).
This syntax is useful for functions that require a class name. For example, it can be used with
class_exists to
check a class exists. No errors will be generated regardless of return value in this snippet:
class_exists(ThisClass\Will\NeverBe\Loaded::class, false);
An abstract class is a class that cannot be instantiated. Abstract classes can define abstract methods,
which are
Abstract classes should be extended by a child class which can then provide the implementation of
these abstract
methods.
The main purpose of a class like this is to provide a kind of template that allows children classes to
inherit from,
In this example we will be implementing a Worker interface. First we define the interface:
interface Worker {
To ease the development of further Worker implementations, we will create an abstract worker class
that already
provides the run() method from the interface, but specifies some abstract methods that need to be
filled in by any
child class:
protected $logger;
$this->pdo = $pdo;
$this->logger = $logger;
try {
$this->setMemoryLimit($this->getMemoryLimit());
$this->logger->log("Preparing main");
$this->prepareMain();
$this->logger->log("Executing main");
$this->main();
// Catch and rethrow all errors so they can be logged by the worker
throw $e;
ini_set('memory_limit', $memoryLimit);
First of all, we have provided an abstract method getMemoryLimit(). Any class extending from
AbstractWorker
needs to provide this method and return its memory limit. The AbstractWorker then sets the memory
limit and
logs it.
Secondly the AbstractWorker calls the prepareMain() and main() methods, after logging that they have
been
called.
Finally, all of these method calls have been grouped in a try-catch block. So if any of the abstract
methods defined
by the child class throws an exception, we will catch that exception, log it and rethrow it. This prevents
all child
Now lets define a child class that extends from the AbstractWorker:
private $transactions;
return "512M";
$stmt->execute();
$this->transactions = $stmt->fetchAll();
}
protected function main() {
// Could throw some PDO or MYSQL exception, but that is handled by the AbstractWorker
$stmt->execute();
As you can see, the TransactionProcessorWorker was rather easy to implement, as we only had to
specify the
memory limit and worry about the actual actions that it needed to perform. No error handling is
needed in the
Important Note
When inheriting from an abstract class, all methods marked abstract in the parent's class declaration
must be defined by the child (or the child itself must also be marked abstract); additionally, these
methods must be defined with the same (or a less restricted) visibility. For example, if the abstract
method is defined as protected, the function implementation must be defined as either protected or
If you do not define the parent abstract classes methods within the child class, you will be thrown a
Fatal PHP
Fatal error: Class X contains 1 abstract method and must therefore be declared abstract or implement
from. It was added to overcome the problem inherent with the self:: scope resolutor. Take the
following code
class Horse {
echo 'Neigh!';
self::whatToSay();
You would expect that the MrEd class will override the parent whatToSay() function. But when we run
this we get
something unexpected
Horse::speak(); // Neigh!
MrEd::speak(); // Neigh!
The problem is that self::whatToSay(); can only refer to the Horse class, meaning it doesn't obey MrEd.
If we
switch to the static:: scope resolutor, we don't have this problem. This newer method tells the class to
obey the
instance calling it. Thus we get the inheritance we're expecting
class Horse {
echo 'Neigh!';
Horse::speak(); // Neigh!
Technically, autoloading works by executing a callback when a PHP class is required but not found.
Such callbacks
Generally, autoloading can be understood as the attempt to load PHP files (especially PHP class files,
where a PHP
source file is dedicated for a specific class) from appropriate paths according to the class's fully-
qualified name
<?php
<?php
namespace application\controllers { class Control {...} }
<?php
Under the source folder, these classes should be placed at the paths as their FQNs respectively:
Source folder
applications
controllers
Base.php
Control.php
models
Page.php
This approach makes it possible to programmatically resolve the class file path according to the FQN,
using this
function:
return $sourceFolder . "/" . str_replace("\\", "/", $className) . $extension; // note that "/"
The spl_autoload_register function allows us to load a class when needed using a user-defined
function:
});
This function can be further extended to use fallback methods of loading:
foreach(SOURCE_FOLDERS as $folder) {
$extensions = [
// do we have src/Foo/Bar.php5_int64?
// do we have src/Foo/Bar.php7?
".php" . PHP_MAJOR_VERSION,
// do we have src/Foo/Bar.php_int64?
// do we have src/Foo/Bar.phps?
".phps"
// do we have src/Foo/Bar.php?
".php"
];
foreach($extensions as $ext) {
});
Note that PHP doesn't attempt to load the classes whenever a file that uses this class is loaded. It may
be loaded in
the middle of a script, or even in shutdown functions . This is one of the reasons why developers,
especially those
who use autoloading, should avoid replacing executing source files in the runtime, especially in phar
files.
There are three visibility types that you can apply to methods (class/object functions) and properties
(class/object
variables) within a class, which provide access control for the method or property to which they are
applied.
You can read extensively about these in the PHP Documentation for OOP Visibility.
Public
Declaring a method or a property as public allows the method or property to be accessed by:
class MyClass {
// Property
// Method
return $this->myProperty;
echo $obj->myMethod();
// Out: test
echo $obj->myProperty;
// Out: test
Protected
Declaring a method or a property as protected allows the method or property to be accessed by:
This does not allow external objects, classes, or code outside the class hierarchy to access these
methods or
properties. If something using this method/property does not have access to it, it will not be available,
and an error
will be thrown. Only instances of the declared self (or subclasses thereof) have access to it.
class MyClass {
return $this->myProperty;
echo $this->myMethod();
// Out: test
$obj->myMethod(); // This will fail.
// Out: Fatal error: Call to protected method MyClass::myMethod() from context ''
The example above notes that you can only access the protected elements within it's own scope.
Essentially: "What's in
Private
Declaring a method or a property as private allows the method or property to be accessed by:
A private method or property is only visible and accessible within the class that created it.
Note that objects of the same type will have access to each others private and protected members
even though
class MyClass {
return $this->myProperty;
return $this->myPrivateMethod();
echo $this->myPrivateMethod();
// MyClass::myPrivateMethod();
$obj->run();
// Out: test
$obj->modifyPrivatePropertyOf($newObj);
$newObj->run();
// Out: Fatal error: Call to private method MyClass::myPrivateMethod() from context ''
// Out: Fatal error: Call to private method MyClass::myPrivateMethod() from context 'MySubClass'
As noted, you can only access the private method/property from within it's defined class.
Introduction
Interfaces are definitions of the public APIs classes must implement to satisfy the interface. They work
as
"contracts", specifying what a set of subclasses does, but not how they do it.
Interface definition is much alike class definition, changing the keyword class to interface:
interface Foo {
Interfaces can contain methods and/or constants, but no attributes. Interface constants have the same
restrictions
interface Foo {
Note: interfaces must not declare constructors or destructors, since these are implementation details
on the class
level.
Realization
Any class that needs to implement an interface must do so using the implements keyword. To do so,
the class
needs to provide a implementation for every method declared in the interface, respecting the same
signature.
interface Foo {
interface Bar {
}
class Baz implements Foo, Bar {
// ...
// ...
When abstract classes implement interfaces, they do not need to implement all methods. Any method
not
implemented in the base class must then be implemented by the concrete class that extends it:
// ...
// ...
Notice that interface realization is an inherited characteristic. When extending a class that implements
an interface,
Note: Prior to PHP 5.3.9, a class could not implement two interfaces that specified a method with the
same name, since it would cause ambiguity. More recent versions of PHP allow this as long as the
Inheritance
Like classes, it is possible to establish an inheritance relationship between interfaces, using the same
keyword
extends. The main difference is that multiple inheritance is allowed for interfaces:
interface Foo {
interface Bar {
Examples
In the example bellow we have a simple example interface for a vehicle. Vehicles can go forwards and
backwards.
interface VehicleInterface {
...
$this->pedal();
...
...
...
$this->setGear(1);
$this->pushPedal();
$this->setGear('R');
$this->pushPedal();
$this->gear = $gear;
...
}
...
Then we create two classes that implement the interface: Bike and Car. Bike and Car internally are very
different,
but both are vehicles, and must implement the same public methods that VehicleInterface provides.
Typehinting allows methods and functions to request Interfaces. Let's assume that we have a parking
garage class,
class ParkingGarage {
$this->vehicles[] = $vehicle;
input both Bikes and Cars, which the ParkingGarage can manipulate and use.
Def: Final Keyword prevents child classes from overriding a method by prefixing the definition with
final. If the class
Final Method
class BaseClass {
Final Class:
// Results in Fatal error: Class ChildClass may not inherit from final class (BaseClass)
Final constants: Unlike Java, the final keyword is not used for class constants in PHP. Use the keyword
const
instead.
2. Encouraging composition
When to avoid final: Final classes only work effectively under following assumptions:
2. All of the public API of the final class is part of that interface
Nobody wants to require or include every time a class or inheritance is used. Because it can be painful
and is easy
to forget, PHP is offering so called autoloading. If you are already using Composer, read about
autoloading using
Composer.
The name basically says it all. You do not have to get the file where the requested class is stored in, but
PHP
functions will be considered by PHP every time a class is not defined within the given space. So adding
autoload to
an existing project is no problem, as defined classes (via require i.e.) will work like before. For the sake
of
preciseness, the following examples will use anonymous functions, if you use PHP < 5.3, you can
define the function
Examples
spl_autoload_register(function ($className) {
if (file_exists($path)) {
include $path;
} else {
});
The code above simply tries to include a filename with the class name and the appended extension
".php" using
sprintf. If FooBar needs to be loaded, it looks if FooBar.php exists and if so includes it.
Of course this can be extended to fit the project's individual need. If _ inside a class name is used to
group, e.g.
User_Post and User_Image both refer to User, both classes can be kept in a folder called "User" like so:
spl_autoload_register(function ($className) {
if (file_exists($path)) {
include $path;
} else {
});
spl_autoload_register can be tailored to various needs. All your files with classes are named
problem either.
If you want a more elaborate autoloading mechanism - and still don't want to include Composer - you
can work
spl_autoload_register(function ($className) {
$path = sprintf('%1$s%2$s%3$s.php',
realpath(dirname(__FILE__)),
DIRECTORY_SEPARATOR,
// %3$s: don't wory about caps or not when creating the files
strtolower(
);
if (file_exists($path)) {
include $path;
} else {
$className,
$path
);
});
Using autoloaders like this, you can happily write code like this:
Using classes:
These examples will be include classes from foo/bar.php, foo.php, hello/world.php and
demo/classes.php.
a child
A common pitfall of child classes is that, if your parent and child both contain a
constructor(__construct())
method, only the child class constructor will run. There may be occasions where you need to run the
parent
__construct() method from it's child. If you need to do that, then you will need to use the parent::
scope
resolutor:
parent::__construct();
Now harnessing that within a real-world situation would look something like:
class Foo {
function __construct($args) {
echo 'parent';
function __construct($args) {
parent::__construct($args);
The above will run the parent __construct() resulting in the echo being run.
Dynamic binding, also referred as method overriding is an example of run time polymorphism that
occurs when
multiple classes contain different implementations of the same method, but the object that the
method will be
This is useful if a certain condition dictates which class will be used to perform an action, where the
action is named
interface Animal {
}
class Cat implements Animal {
$this->meow();
...
$this->bark();
...
class Person {
private $petPreference;
private $pet;
}
public function setPet(Animal $pet) {
$this->pet = $pet;
return $this->pet;
if($person->isCatLover()) {
$person->setPet(new Cat());
} else if($person->isDogLover()) {
$person->setPet(new Dog());
$person->getPet()->makeNoise();
In the above example, the Animal class (Dog|Cat) which will makeNoise is unknown until run time
depending on the
Use $this to refer to the current object. Use self to refer to the current class. In other words, use
In the example below, sayHello() and sayGoodbye() are using self and $this difference can be observed
here.
class Person {
private $name;
$this->name = $name;
}
public function getName() {
return $this->name;
parent::__construct($name);
$geekObj->sayHello();
$geekObj->sayGoodbye();
static refers to whatever class in the hierarchy you called the method on. It allows for better reuse of
static class
class Car {
return self::$brand."\n";
unknown
unknown
unknown
That's because self refers to the Car class whenever method brand() is called.
return static::$brand."\n";
unknown
BMW
Mercedes
The singleton
If you have an object that's expensive to create or represents a connection to some external resource
you want to
reuse, i.e. a database connection where there is no connection pooling or a socket to some other
system, you can
use the static and self keywords in a class to make it a singleton. There are strong opinions about
whether the
singleton pattern should or should not be used, but it does have its uses.
class Singleton {
if(!isset(self::$instance)){
return self::$instance;
// Do constructor stuff
As you can see in the example code we are defining a private static property $instance to hold the
object
reference. Since this is static this reference is shared across ALL objects of this type.
The getInstance()method uses a method know as lazy instantiation to delay creating the object to the
last
possible moment as you do not want to have unused objects lying around in memory never intended
to be used. It
also saves time and CPU on page load not having to load more objects than necessary. The method is
checking if
the object is set, creating it if not, and returning it. This ensures that only one object of this kind is
ever created.
We are also setting the constructor to be private to ensure that no one creates it with the new
keyword from the
outside. If you need to inherit from this class just change the private keywords to protected.
$singleton = Singleton::getInstance();
Now I DO implore you to use dependency injection where you can and aim for loosely coupled
objects, but
sometimes that is just not reasonable and the singleton pattern can be of use.
An object in PHP contains variables and functions. Objects typically belong to a class, which defines
the variables
class Shape {
public $sides = 0;
Constructor
Classes can define a special __construct() method, which is executed as part of object creation. This is
often used
class Shape {
public $sides = 0;
$this->sides = $sides;
Class definitions can extend existing class definitions, adding new variables and functions as well as
modifying
public $sideLength = 0;
public function __construct($sideLength) {
parent::__construct(4);
$this->sideLength = $sideLength;
The Square class contains variables and behavior for both the Shape class and the Square class:
print $mySquare->perimeter() // 40
Anonymous classes were introduced into PHP 7 to enable for quick one-off objects to be easily
created. They can
take constructor arguments, extend other classes, implement interfaces, and use traits just like normal
classes can.
In its most basic form, an anonymous class looks like the following:
new class("constructor argument") {
var_dump($param);
Nesting an anonymous class inside of another class does not give it access to private or protected
methods or
properties of that outer class. Access to protected methods and properties of the outer class can be
gained by
extending the outer class from the anonymous class. Access to private properties of the outer class
can be gained
For example:
class Outer {
private $prop = 1;
protected $prop2 = 2;
return 3;
private $prop3;
$this->prop3 = $prop;
}
public function func3() {
// accessing the local property self::$prop3 that was private from Outer::$prop
};
It is recommended to only declare a single namespace per file, even though you can declare as many
as you like in
a single file:
namespace First {
namespace Second {
}
namespace {
Every time you declare a namespace, classes you define after that will belong to that namespace:
namespace MyProject\Shapes;
A namespace declaration can be used multiple times in different files. The example above defined
three classes in
the MyProject\Shapes namespace in a single file. Preferably this would be split up into three files,
each starting
with namespace MyProject\Shapes;. This is explained in more detail in the PSR-4 standard example.
namespace MyProject\Shapes;
To reference this class the full path (including the namespace) needs to be used:
use MyProject\Shapes\Rectangle;
As for PHP 7.0 you can group various use-statements in one single statement using brackets:
use MyProject\Shapes\{
Rectangle, //Same as `use MyProject\Shapes\Rectangle`
};
Sometimes two classes have the same name. This is not a problem if they are in a different
namespace, but it could
use MyProject\Shapes\Oval;
// Error!
This can be solved by defining a name for the alias yourself using the as keyword:
To reference a class outside the current namespace, it has to be escaped with a \, otherwise a relative
namespace
namespace MyProject\Shapes;
$a = new Rectangle();
$a = new \MyProject\Shapes\Rectangle();
$a = new \StdClass();
$a = new StdClass();
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
constant MyProject\Sub\Level\CONNECT_OK
function MyProject\Sub\Level\connect
The PHP community has a lot of developers creating lots of code. This means that one library’s PHP
code may use
the same class name as another library. When both libraries are used in the same namespace, they
collide and
cause trouble.
Namespaces solve this problem. As described in the PHP reference manual, namespaces may be
compared to
operating system directories that namespace files; two files with the same name may co-exist in
separate
directories. Likewise, two PHP classes with the same name may co-exist in separate PHP namespaces.
It is important for you to namespace your code so that it may be used by other developers without
fear of colliding
Starting with PHP Sessions we can pass an array with session-based php.ini options to the
session_start
function.
Example
<?php
session_start([
]);
} else {
session_start();
?>
This feature also introduces a new php.ini setting named session.lazy_write, which defaults to true
and means
As we all are aware that PHP writes session data into a file at server side. When a request is made to
php script
which starts the session via session_start(), PHP locks this session file resulting to block/wait other
incoming
requests for same session_id to complete, because of which the other requests will get stuck on
session_start()
The session file remains locked until the script is completed or session is manually closed. To avoid this
situation i.e.
to prevent multiple requests getting blocked, we can start the session and close the session which will
release the lock
// start session
session_start();
session_write_close();
Now one will think if session is closed how we will read the session values, beautify even after session
is closed,
session is still available. So, we can still read the session data.
In php >= 7.0, we can have read_only session, read_write session and lazy_write session, so it may not
required
to use session_write_close()
GoalKicker.com – PHP Notes for Professionals 166
The $_SESSION variable is an array, and you can retrieve or manipulate it like a normal array.
<?php
session_start();
$_SESSION['id'] = 342;
// conditional usage of session values that may have been set in a previous session
if(!isset($_SESSION["login"])) {
exit;
$user = $_SESSION["login"];
Also see Manipulating an Array for more reference how to work on an array.
Note that if you store an object in a session, it can be retrieved gracefully only if you have an class
autoloader or
you have loaded the class already. Otherwise, the object will come out as the type
__PHP_Incomplete_Class, which
may later lead to crashes. See Namespacing and Autoloading about autoloading.
Warning:
Session data can be hijacked. This is outlined in: Pro PHP Security: From Application Security Principles
to the
Implementation of XSS Defense - Chapter 7: Preventing Session Hijacking So it can be strongly
recommended to never
store any personal information in $_SESSION. This would most critically include credit card numbers,
government
issued ids, and passwords; but would also extend into less assuming data like names, emails, phone
numbers,
etc which would allow a hacker to impersonate/compromise a legitimate user. As a general rule, use
worthless/nonpersonal values, such as numerical identifiers, in session data.
If you've got a session which you wish to destroy, you can do this with session_destroy()
/*
*/
session_start();
/*
We can now remove all the values from the `SESSION` superglobal:
If you omitted this step all of the global variables stored in the
superglobal would still exist even though the session had been destroyed.
*/
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
Using session_destroy() is different to using something like $_SESSION = array(); which will remove all
of the
values stored in the SESSION superglobal but it will not destroy the actual stored version of the
session.
Note: We use $_SESSION = array(); instead of session_unset() because the manual stipulates:
Only use session_unset() for older deprecated code that does not use $_SESSION.
Many developers have this problem when they work on huge projects, especially if they work on some
modular
CMS on plugins, addons, components etc. Here is solution for safe session start where if first checked
PHP version
to cover all versions and on next is checked if session is started. If session not exists then I start session
safe. If
if(session_status() == PHP_SESSION_NONE) {
session_start(array(
));
}
if (session_status() == PHP_SESSION_NONE) {
session_start();
else
if(session_id() == '') {
session_start();
Session name is the name of the cookie used to store sessions. You can use this to detect if cookies for
a session
if(isset($_COOKIE[session_name()])) {
session_start();
Note that this method is generally not useful unless you really don't want to create cookies
unnecessarily.
Changing session name
session_name('newname');
session_start();
If no argument is provided into session_name() then the current session name is returned.
It should contain only alphanumeric characters; it should be short and descriptive (i.e. for users with
enabled cookie warnings). The session name can't consist of digits only, at least one letter must be
parameter detail
name
The name of the cookie. This is also the key you can use to retrieve the value from the $_COOKIE super
value The value to store in the cookie. This data is accessible to the browser so don't store anything
sensitive
here.
expire
A Unix timestamp representing when the cookie should expire. If set to zero the cookie will expire at
the end of the session. If set to a number less than the current Unix timestamp the cookie will expire
immediately.
path
The scope of the cookie. If set to / the cookie will be available within the entire domain. If set to
/somepath/ then the cookie will only be available in that path and descendants of that path. Defaults
to the
current path of the file that the cookie is being set in.
domain
The domain or subdomain the cookie is available on. If set to the bare domain stackoverflow.com
then the cookie will be available to that domain and all subdomains. If set to a subdomain
meta.stackoverflow.com then the cookie will be available only on that subdomain, and all
subsubdomains.
secure
When set to TRUE the cookie will only be set if a secure HTTPS connection exists between the client
and
the server.
httponly Specifies that the cookie should only be made available through the HTTP/S protocol and
should not
be available to client side scripting languages like JavaScript. Only available in PHP 5.2 or later.
An HTTP cookie is a small piece of data sent from a website and stored on the user's computer by the
user's web
setcookie("user", "John", time() + 86400, "/"); // assuming there is a "user" cookie already
Cookies are part of the HTTP header, so setcookie() must be called before any output is sent to the
browser.
When modifying a cookie make sure the path and domain parameters of setcookie() matches the
The value portion of the cookie will automatically be urlencoded when you send the cookie, and when
it is
received, it is automatically decoded and assigned to a variable by the same name as the cookie name
Example:
setcookie("user", "Tom", time() + 86400, "/"); // check syntax for function params
Description:
A created or modified cookie can only be accessed on subsequent requests (where path and domain
matches) as the superglobal $_COOKIEis not populated with the new data immediately.
Use the isset() function upon the superglobal $_COOKIE variable to check if a cookie is set.
Example:
// PHP <7.0
if (isset($_COOKIE['user'])) {
else {
}
// PHP 7.0+
To remove a cookie, set the expiry timestamp to a time in the past. This triggers the browser's removal
mechanism:
When deleting a cookie make sure the path and domain parameters of setcookie() matches the cookie
you're trying to delete or a new cookie, which expires immediately, will be created.
It is also a good idea to unset the $_COOKIE value in case the current page uses it:
unset($_COOKIE['user']);
The value of a cookie can be retrieved using the global variable $_COOKIE. example if we have a
cookie named user
echo $_COOKIE['user'];
Function Details
ob_start() Starts the output buffer, any output placed after this will be captured and not displayed
ob_end_clean() Empties the output buffer and turns it off for the current nesting level
ob_flush() Flush the content buffer and send it to the browser without ending the buffer
and clearing
Output buffering allows you to store any textual content (Text, HTML) in a variable and send to the
browser as one
piece at the end of your script. By default, php sends your content as it interprets it.
<?php
ob_start();
?>
<em>World</em>
<?php
$content = ob_get_clean();
# $content = ob_get_contents();
# $did_clear_buffer = ob_end_clean();
print($content);
Any content outputted between ob_start() and ob_get_clean() will be captured and placed into the
variable
$content.
You can apply any kind of additional processing to the output by passing a callable to ob_start().
<?php
function clearAllWhiteSpace($buffer) {
ob_start('clearAllWhiteSpace');
?>
<h1>Lorem Ipsum</h1>
<ol>
</ol>
<?php
ob_end_flush();
*/
Output:
<h1>LoremIpsum</h1><p><strong>Pellentesquehabitantmorbitristique</
strong>senectusetnetusetmalesuada
famesacturpisegestas.<ahref="#">Donecnonenim</a>inturpispulvinarfacilisis.</
p><h2>HeaderLevel2</h2>
<ol><li>Loremipsumdolorsitamet,consectetueradipiscingelit.</
li><li>Aliquamtinciduntmauriseurisus.</
li></ol>
You can nest output buffers and fetch the level for them to provide different content using the
ob_get_level()
function.
<?php
$i = 1;
$output = null;
while( $i <= 5 ) {
ob_start();
$i++;
// Get clean will `pop` the contents of the top most level (5)
$output .= ob_get_clean();
print $output;
// For each level we went up, come back down and get the buffer
while( $i > 2 ) {
$i--;
Outputs:
Ended up at level: 5
ob_start();
$user_count = 0;
?>
</li>
<?php
$user_count++;
$users_html = ob_get_clean();
if( !$user_count ) {
header('Location: /404.php');
exit();
?>
<html>
<head>
</head>
<body>
<h2>We have a total of <?php echo $user_count; ?> users with access level 7</h2>
<ul class="user-list">
</ul>
</body>
</html>
In this example we assume $users to be a multidimensional array, and we loop through it to find all
users with an
access level of 7.
/**
*/
function _stream() {
ob_implicit_flush(true);
ob_end_flush();
<?php
ob_start();
?>
<html>
<head>
<title>Example invoice</title>
</head>
<body>
<h1>Invoice #0000</h1>
<h2>Cost: £15,000</h2>
...
</body>
</html>
<?php
$html = ob_get_clean();
fwrite($handle, $html);
fclose($handle);
This example takes the complete document, and writes it to file, it does not output the document into
the browser,
ob_start is especially handy when you have redirections on your page. For example, the following
code won't work:
Hello!
<?php
header("Location: somepage.php");
?>
The error that will be given is something like: headers already sent by <xxx> on line <xxx>.
In order to fix this problem, you would write something like this at the start of your page:
<?php
ob_start();
?>
<?php
ob_end_flush();
?>
This stores all generated content into an output buffer, and displays it in one go. Hence, if you have
any redirection
calls on your page, those will trigger before any data is sent, removing the possibility of a headers
already sent
error occurring.
We capture the output buffer in $items_li_html and use it twice in the page.
<?php
ob_start();
foreach($items as $item):
?>
<?php
endforeach;
$items_li_html = ob_get_clean();
?>
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<ul class="footer-nav">
</ul>
Save the above code in a file output_buffer.php and run it via php output_buffer.php.
You should see the 2 list items we created above with the same list items we generated in PHP using
the output
buffer:
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<li>Home</li>
<li>Blog</li>
<li>FAQ</li>
<li>Contact</li>
</ul>
<ul class="footer-nav">
<li>Home</li>
<li>Blog</li>
<li>FAQ</li>
<li>Contact</li>
</ul>
json_encode -
value The value being encoded. Can be any type except a resource. All string data must be UTF-8
encoded.
options
JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE,
JSON_PARTIAL_OUTPUT_ON_ERROR.
json_decode -
json The json string being decoded. This function only works with UTF-8 encoded strings.
JSON (JavaScript Object Notation) is a platform and language independent way of serializing objects
into plaintext.
Because it is often used on web and so is PHP, there is a basic extension for working with JSON in PHP.
The json_decode() function takes a JSON-encoded string as its first parameter and parses it into a PHP
variable.
Normally, json_decode() will return an object of \stdClass if the top level item in the JSON object is a
dictionary or
an indexed array if the JSON object is an array. It will also return scalar values or NULL for certain
scalar values,
such as simple strings, "true", "false", and "null". It also returns NULL on any error.
// Returns an object (The top level item in the JSON string is a JSON dictionary)
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$object = json_decode($json_string);
// Returns an array (The top level item in the JSON string is a JSON array)
$array = json_decode($json_string);
Use var_dump() to view the types and values of each property on the object we decoded above.
var_dump($object);
["colors"] =>
array(2) {
Note: The variable types in JSON were converted to their PHP equivalent.
To return an associative array for JSON objects instead of returning an object, pass true as the second
parameter
to json_decode().
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
var_dump($array);
array(4) {
["colors"] =>
array(2) {
The second parameter ($assoc) has no effect if the variable to be returned is not an object.
Note: If you use the $assoc parameter, you will lose the distinction between an empty array and an
empty object.
This means that running json_encode() on your decoded output again, will result in a different JSON
structure.
If the JSON string has a "depth" more than 512 elements (20 elements in versions older than 5.2.3, or
128 in version
5.2.3) in recursion, the function json_decode() returns NULL. In versions 5.3 or later, this limit can be
controlled
PHP implements a superset of JSON as specified in the original » RFC 4627 - it will also encode and
decode scalar types and NULL. RFC 4627 only supports these values when they are nested inside an
array
or an object. Although this superset is consistent with the expanded definition of "JSON text" in the
newer
» RFC 7159 (which aims to supersede RFC 4627) and » ECMA-404, this may cause interoperability
issues
with older JSON parsers that adhere strictly to RFC 4627 when encoding a single scalar value.
This means, that, for example, a simple string will be considered to be a valid JSON object in PHP:
var_dump($json, json_last_error_msg());
Output:
But simple strings, not in an array or object, are not part of the RFC 4627 standard. As a result, such
online checkers
as JSLint, JSON Formatter & Validator (in RFC 4627 mode) will give you an error.
There is a third $depth parameter for the depth of recursion (the default value is 512), which means
the amount of
There is a fourth $options parameter. It currently accepts only one value, JSON_BIGINT_AS_STRING.
The default
behavior (which leaves off this option) is to cast large integers to floats instead of strings.
Invalid non-lowercased variants of the true, false and null literals are no longer accepted as valid
input.
So this example:
var_dump(json_decode('tRue'), json_last_error_msg());
var_dump(json_decode('tRUe'), json_last_error_msg());
var_dump(json_decode('tRUE'), json_last_error_msg());
var_dump(json_decode('TRUe'), json_last_error_msg());
var_dump(json_decode('TRUE'), json_last_error_msg());
var_dump(json_decode('true'), json_last_error_msg());
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
And after:
NULL
NULL
NULL
string(12) "Syntax error"
NULL
NULL
bool(true)
Note that json_decode() will return NULL if the string cannot be converted.
$person = json_decode($json);
echo json_last_error();
# 4 (JSON_ERROR_SYNTAX)
echo json_last_error_msg();
# unexpected character
It is not safe to rely only on the return value being NULL to detect errors. For example, if the JSON
string contains
nothing but "null", json_decode() will return null, even though no error occurred.
The json_encode function will convert a PHP array (or, since PHP 5.4, an object which implements the
failure.
$array = [
'name' => 'Jeff',
];
During encoding, the PHP data types string, integer, and boolean are converted to their JSON
equivalent.
Associative arrays are encoded as JSON objects, and – when called with default arguments – indexed
arrays are
encoded as JSON arrays. (Unless the array keys are not a continuous numeric sequence starting from 0,
in which
echo json_encode($array);
Output:
{"name":"Jeff","age":20,"active":true,"colors":["red","blue"],"values":{"0":"foo","3":"bar"}}
Arguments
Since PHP 5.3, the second argument to json_encode is a bitmask which can be one or more of the
following.
As with any bitmask, they can be combined with the binary OR operator |.
JSON_FORCE_OBJECT
echo json_encode($array);
Output:
["Joel",23,true,["red","blue"]]
{"0":"Joel","1":23,"2":true,"3":{"0":"red","1":"blue"}}
echo json_encode($array);
Output:
{"tag":"<>","amp":"&","apos":"'","quot":"\""}
{"tag":"\u003C\u003E","amp":"\u0026","apos":"\u0027","quot":"\u0022"}
JSON_NUMERIC_CHECK
echo json_encode($array);
Output:
["23452",23452]
[23452,23452]
JSON_PRETTY_PRINT
$array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
echo json_encode($array);
Output:
{"a":1,"b":2,"c":3,"d":4}
"a": 1,
"b": 2,
"c": 3,
"d": 4
JSON_UNESCAPED_SLASHES
echo json_encode($array);
Output:
{"filename":"example.txt","path":"\/full\/path\/to\/file"}
{"filename":"example.txt","path":"/full/path/to/file"}
JSON_UNESCAPED_UNICODE
Includes UTF8-encoded characters in the output instead of \u-encoded strings
echo json_encode($blues);
Output:
{"english":"blue","norwegian":"bl\u00e5","german":"blau"}
{"english":"blue","norwegian":"blå","german":"blau"}
JSON_PARTIAL_OUTPUT_ON_ERROR
Output:
{"file":null,"name":"foo.txt"}
JSON_PRESERVE_ZERO_FRACTION
echo json_encode($array);
Output:
[5,5.5]
[5.0,5.5]
PHP 7.x Version ≥ 7.1
JSON_UNESCAPED_LINE_TERMINATORS
When used with JSON_UNESCAPED_UNICODE, reverts to the behaviour of older PHP versions, and
does not escape the
characters U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR. Although valid in JSON,
these characters
are not valid in JavaScript, so the default behaviour of JSON_UNESCAPED_UNICODE was changed in
version 7.1.
Output:
{"line":"\u2028","paragraph":"\u2029"}
{"line":"","paragraph":""}
When json_encode or json_decode fails to parse the string provided, it will return false. PHP itself will
not raise
any errors or warnings when this happens, the onus is on the user to use the json_last_error() and
json_last_error_msg() functions to check if an error occurred and act accordingly in your application
(debug it, show
The following example shows a common error when working with JSON, a failure to decode/encode a
JSON string
if (json_last_error() != JSON_ERROR_NONE) {
printf("JSON Error: %s", json_last_error_msg());
json_last_error_msg
json_last_error_msg() returns a human readable message of the last error that occurred when trying
to
encode/decode a string.
Careful when using this in loops, as json_last_error_msg will be overridden on each iteration.
You should only use this function to get the message for display, not to test against in control
statements.
// Don't do this:
if (json_last_error() != JSON_ERROR_NONE) {
// Use json_last_error_msg to display the message only, (not test against it)
This function doesn't exist before PHP 5.5. Here is a polyfill implementation:
if (!function_exists('json_last_error_msg')) {
function json_last_error_msg() {
);
$error = json_last_error();
json_last_error
json_last_error() returns an integer mapped to one of the pre-defined constants provided by PHP.
Constant Meaning
JSON_ERROR_UTF8 Malformed UTF-8 characters, possibly incorrectly encoded (since PHP 5.5.0)
application. For this purpose, this example illustrates how to use the JsonSerialiazble interface.
In this example, the class User actually extends a DB model object of a hypotetical ORM.
public $id;
public $name;
public $surname;
public $username;
public $password;
public $email;
public $date_created;
public $date_edit;
public $role;
public $status;
return [
];
Now in your application controller or script, when passing the object User to json_encode() you will
get the return
json encoded array of the jsonSerialize() method instead of the entire object.
json_encode($User);
Will return:
This will both reduce the amount of data returned from a RESTful endpoint, and allow to exclude
object properties
To avoid using JsonSerializable, it is also possible to use private or protected properties to hide class
information
from json_encode() output. The Class then does not need to implement \JsonSerializable.
The json_encode() function will only encode public properties of a class into JSON.
<?php
class User {
private $id;
private $date_created;
private $date_edit;
protected $password;
protected $email;
protected $role;
protected $status;
// share these properties with the end user
public $name;
public $surname;
public $username;
var_dump(json_encode($theUser));
Output:
string(44) "{"name":null,"surname":null,"username":null}"
<?php
$result = array('menu1' => 'home', 'menu2' => 'code php', 'menu3' => 'about');
exit();
The header is there so your app can detect what data was returned and how it should handle it.
Note that: the content header is just information about type of returned data.
header("Content-Type: application/json;charset=utf-8");
Example jQuery:
$.ajax({
url:'url_your_page_php_that_return_json'
}).done(function(data){
console.table('json ',data);
});
Parameter Details
$options Array of options for SoapClient. Non-WSDL mode requires location and uri to set, all other
options
First, create a new SoapClient object, passing the URL to the WSDL file and optionally, an array of
options.
]);
This is similar to WSDL mode, except we pass NULL as the WSDL file and make sure to set the location
and uri
options.
]);
When creating a SOAP Client in PHP, you can also set a classmap key in the configuration array. This
classmap
defines which types defined in the WSDL should be mapped to actual classes, instead of the default
StdClass. The
reason you would want to do this is because you can get auto-completion of fields and method calls
on these
classes, instead of having to guess which fields are set on the regular StdClass.
class MyAddress {
public $country;
public $city;
public $full_name;
public $house_number;
class MyBook {
public $name;
public $author;
GoalKicker.com – PHP Notes for Professionals 188
// Other parameters
"classmap" => [
]);
After configuring the classmap, whenever you perform a certain operation that returns a type Address
or Book, the
SoapClient will instantiate that class, fill the fields with the data and return it from the operation call.
$address = $soap_client->getAddress(1234);
echo $address->country;
$book = $soap_client->getBook(124);
echo $book->getShortDescription();
// Any type defined in the WSDL that is not defined in the classmap
// will become a regular StdClass object
$author = $soap_client->getAuthor(1234);
echo $author->name;
Sometimes we want to look at what is sent and received in the SOAP request. The following methods
will return the
SoapClient::__getLastRequest()
SoapClient::__getLastRequestHeaders()
SoapClient::__getLastResponse()
SoapClient::__getLastResponseHeaders()
For example, suppose we have an ENVIRONMENT constant and when this constant's value is set to
DEVELOPMENT we
want to echo all information when the call to getAddress throws an error. One solution could be:
try {
$address = $soap_client->getAddress(1234);
var_dump(
$soap_client->__getLastRequestHeaders()
$soap_client->__getLastRequest(),
$soap_client->__getLastResponseHeaders(),
$soap_client->__getLastResponse()
);
...
Parameter Details
option CURLOPT_XXX to be set - see PHP documentation for the list of options and acceptable values
value The value to be set on the cURL handle for the given option
cURL is a tool for transferring data with URL syntax. It support HTTP, FTP, SCP and many others(curl >=
7.19.4).
Remember, you need to install and enable the cURL extension to use it.
if(!extension_loaded("curl")) {
}
// Actual script start
$curl = curl_init();
curl_exec($curl);
curl_close($curl);
If you want to mimic HTML form POST action, you can use cURL.
$post = [
];
$ch = curl_init('http://www.example.com');
curl_close($ch);
cURL can keep cookies received in responses for use with subsequent requests. For simple session
cookie handling
In cases where you are required to keep cookies after the cURL handle is destroyed, you can specify
the file to store
them in:
Then, when you want to use them again, pass them as the cookie file:
Remember, though, that these two steps are not necessary unless you need to carry cookies between
different
cURL handles. For most use cases, setting CURLOPT_COOKIEFILE to the empty string is all you need.
Cookie handling can be used, for example, to retrieve resources from a web site that requires a login.
This is
<?php
$ch = curl_init();
"username"=>"joe_bloggs",
"password"=>"$up3r_$3cr3t",
));
$result = curl_exec($ch);
The second step (after standard error checking is done) is usually a simple GET request. The important
thing is to
reuse the existing cURL handle for the second request. This ensures the cookies from the first response
will be
$result = curl_exec($ch);
This is only intended as an example of cookie handling. In real life, things are usually more
complicated. Often you
must perform an initial GET of the login page to pull a login token that needs to be included in your
POST. Other
sites might block the cURL client based on its User-Agent string, requiring you to change it.
requests
Sometimes we need to make a lot of POST requests to one or many different endpoints. To deal with
this scenario,
First of all, we create how many requests as needed exactly in the same way of the simple example
and put them in
an array.
$request_contents = array();
//array of URLs
$urls = array();
$chs = array();
$request_contents[] = [
$request_contents[] = [
];
$urls[] = 'http://www.example.com';
$urls[] = 'http://www.example2.com';
$mh = curl_multi_init();
$chs[$key] = curl_init($url);
curl_multi_add_handle($mh, $chs[$key]);
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
//getting the responses
foreach(array_keys($chs) as $key){
$error = curl_error($chs[$key]);
if (!empty($error)) {
else {
curl_multi_remove_handle($mh, $chs[$key]);
curl_multi_close($mh);
Let's say we have a form like the one below. We want to send the data to our webserver via AJAX and
from there to
So we have normal inputs, a multi-select field and a file dropzone where we can upload multiple files.
Assuming the AJAX POST request was successful we get the following data on PHP site:
// print_r($_POST)
Array
// print_r($_FILES)
Array
[0] => 0
[1] => 0
So far, so good. Now we want to send this data and files to the external server using cURL with the
CurlFile Class
Since cURL only accepts a simple but not a multi-dimensional array, we have to flatten the $_POST
array first.
To do this, you could use this function for example which gives you the following:
// print_r($new_post_array)
Array
The next step is to create CurlFile Objects for the uploaded files. This is done by the following loop:
$files = array();
if ($error == UPLOAD_ERR_OK) {
$files["upload[$key]"] = curl_file_create(
$_FILES['upload']['tmp_name'][$key],
$_FILES['upload']['type'][$key],
$_FILES['upload']['name'][$key]
);
curl_file_create is a helper function of the CurlFile Class and creates the CurlFile objects. We save each
object in the
$files array with keys named "upload[0]" and "upload[1]" for our two files.
We now have to combine the flattened post array and the files array and save it as $data like this:
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLINFO_HEADER_OUT => 1,
));
$result = curl_exec($ch);
curl_close ($ch);
Since $data is now a simple (flat) array, cURL automatically sends this POST request with Content
Type:
multipart/form-data
In upload.php on the external server you can now get the post data and files with $_POST and $_FILES
as you would
normally do.
method
By default, PHP Curl supports GET and POST requests. It is possible to also send custom requests, such
as DELETE,
PUT or PATCH (or even non-standard methods) using the CURLOPT_CUSTOMREQUEST parameter.
$ch = curl_init($url);
$content = curl_exec($ch);
curl_close($ch);
Section 33.7: Get and Set custom http headers in php
$uri = 'http://localhost/http.php';
$ch = curl_init($uri);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_VERBOSE => 1
));
$out = curl_exec($ch);
curl_close($ch);
echo $out;
print_r(apache_request_headers());
Output:
Array
[Content-Length] => 9
Feature detection of classes can partly be done with the property_exists and method_exists functions.
class MyClass {
public $public_field;
protected $protected_field;
private $private_field;
static $static_field;
const CONSTANT = 0;
// check properties
// check methods
$check = method_exists('MyClass', 'public_function'); // true
// however...
$r = new ReflectionClass('MyClass');
Note: for property_exists and method_exists, also an object of the class of interest can be provided
instead of the
class name. Using reflection, the ReflectionObject class should be used instead of ReflectionClass.
Sometimes it's useful to test private & protected methods as well as public ones.
class Car
/**
* @return mixed
*/
return $argument;
/**
* @return bool
*/
return true;
class DriveTest
/**
* @test
*/
// prepare
$argument = 1;
$expected = $argument;
$method->setAccessible(true);
// invoke logic
// test
$this->assertEquals($expected, $result);
If the method is static you pass null in the place of the class instance
class StopTest
/**
* @test
*/
// prepare
$expected = true;
$method = $reflection->getMethod('stop');
$method->setAccessible(true);
// invoke logic
$result = $method->invoke(null);
// test
$this->assertEquals($expected, $result);
}
variables
Reflection is often used as part of software testing, such as for the runtime creation/instantiation of
mock objects.
It's also great for inspecting the state of an object at any given point in time. Here's an example of
using Reflection
in a unit test to verify a protected class member contains the expected value.
Below is a very basic class for a Car. It has a protected member variable that will contain the value
representing the
color of the car. Because the member variable is protected we cannot access it directly and must use a
getter and
class Car
protected $color
$this->color = $color;
return $this->color;
}
To test this many developers will create a Car object, set the car's color using Car::setColor(), retrieve
the color
using Car::getColor(), and compare that value to the color they set:
/**
* @test
* @covers \Car::setColor
*/
$color = 'Red';
$car->setColor($color);
$getColor = $car->getColor();
$this->assertEquals($color, $reflectionColor);
On the surface this seems okay. After all, all Car::getColor() does is return the value of the protected
member
2. It depends on Car::getColor() which may have a bug itself which can make the test have a false
positive or
negative
Let's look at why we shouldn't use Car::getColor() in our unit test and should use Reflection instead.
Let's say a
developer is assigned a task to add "Metallic" to every car color. So they attempt to modify the
Car::getColor() to
class Car
protected $color
$this->color = $color;
Do you see the error? The developer used a semi-colon instead of the concatenation operator in an
attempt to
prepend "Metallic" to the car's color. As a result, whenever Car::getColor() is called, "Metallic " will be
returned
regardless of what the car's actual color is. As a result our Car::setColor() unit test will fail even though
Car::setColor() works perfectly fine and was not affected by this change.
So how do we verify Car::$color contains the value we are setting via Car::setColor()? We can use
Refelection to
inspect the protected member variable directly. So how do we do that? We can use Refelection to
make the
protected member variable accessible to our code so it can retrieve the value.
/**
* @test
* @covers \Car::setColor
*/
$color = 'Red';
$car->setColor($color);
$protectedColor = $reflectionOfForm->getProperty('color');
$protectedColor->setAccessible(true);
$reflectionColor = $protectedColor->getValue($car);
$this->assertEquals($color, $reflectionColor);
Here is how we are using Reflection to get the value of Car::$color in the code above:
any other accessor function which could cause invalid test results. Now our unit test for Car::setColor()
is safe
and accurate.
Dependency Injection (DI) is a fancy term for "passing things in". All it really means is passing the
dependencies of an
object via the constructor and / or setters instead of creating them upon object creation inside the
object.
Dependency Injection might also refer to Dependency Injection Containers which automate the
construction and
injection.
Objects will often depend on other objects. Instead of creating the dependency in the constructor, the
dependency
should be passed into the constructor as a parameter. This ensures there is not tight coupling between
the objects,
and enables changing the dependency upon class instantiation. This has a number of benefits,
including making
code easier to read by making the dependencies explicit, as well as making testing simpler since the
dependencies
In the following example, Component will depend on an instance of Logger, but it doesn't create one.
It requires one
interface Logger {
class Component {
private $logger;
$this->logger = $logger;
Without dependency injection, the code would probably look similar to:
class Component {
private $logger;
Using new to create new objects in the constructor indicates that dependency injection was not used
(or was used
incompletely), and that the code is tightly coupled. It is also a sign that the code is incompletely tested
or may have
In the above example, where we are using dependency injection instead, we could easily change to a
different
Logger if doing so became necessary. For example, we might use a Logger implementation that logs to
a different
location, or that uses a different logging format, or that logs to the database instead of to a file.
interface Logger {
public function log($message);
class Component {
private $logger;
private $databaseConnection;
$this->databaseConnection = $databaseConnection;
$this->logger = $logger;
$this->logSave();
return $this->databaseConnection->save($this);
if ($this->logger) {
$this->logger->log('saving');
This is especially interesting when the core functionality of the class does not rely on the dependency
to work.
Here, the only needed dependency is the DatabaseConnection so it's in the constructor. The Logger
dependency is
optional and thus does not need to be part of the constructor, making the class easier to use.
Note that when using setter injection, it's better to extend the functionality rather than replacing it.
When setting a
dependency, there's nothing confirming that the dependency won't change at some point, which
could lead in
unexpected results. For example, a FileLogger could be set at first, and then a MailLogger could be set.
This
breaks encapsulation and makes logs hard to find, because we're replacing the dependency.
To prevent this, we should add a dependency with setter injection, like so:
interface Logger {
class Component {
private $databaseConnection;
$this->databaseConnection = $databaseConnection;
$this->loggers[] = $logger;
$this->logSave();
return $this->databaseConnection->save($this);
Like this, whenever we'll use the core functionality, it won't break even if there is no logger
dependency added, and
any logger added will be used even though another logger could've been added. We're extending
functionality
Dependency Injection (DI) in the context of using a Dependency Injection Container (DIC) can be seen
as a superset
of constructor injection. A DIC will typically analyze a class constructor's typehints and resolve its
needs, effectively
The exact implementation goes well beyond the scope of this document but at its very heart, a DIC
relies on using
namespace Documentation;
class Example
private $meaning;
$this->meaning = $meaning;
}
}
... to automatically instantiate it, relying most of the time on an autoloading system.
$container->make('Documentation\Example');
$container->make(\Documentation\Example::class);
If you are using PHP in version at least 5.5 and want to get a name of a class in a way that's being
shown above, the
correct way is the second approach. That way you can quickly find usages of the class using modern
IDEs, which will
greatly help you with potential refactoring. You do not want to rely on regular strings.
In this case, the Documentation\Example knows it needs a Meaning, and a DIC would in turn
instantiate a Meaning
type. The concrete implementation need not depend on the consuming instance.
Instead, we set rules in the container, prior to object creation, that instructs how specific types should
be
If we define rules about how specific type needs to be managed we can achieve fine control over
which types are
createElement() and createAttribute() methods and them create the XML structure with the
appendChild().
The example below includes tags, attributes, a CDATA section and a different namespace for the
second tag:
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$books = $dom->createElement('books');
$book_1 = $dom->createElement('book');
$attr_1 = $dom->createAttribute('version');
$attr_1->value = '1.0';
$id_1->appendChild($attr_1);
$namespace = 'www.example.com/libraryns/1.0';
$book_2 = $dom->createElementNS($namespace,'ns:book');
$name_2->appendChild($name_cdata);
$books->appendChild($book_1);
$book_1->appendChild($name_1);
$book_1->appendChild($price_1);
$book_1->appendChild($id_1);
$books->appendChild($book_2);
$book_2->appendChild($name_2);
$book_2->appendChild($price_2);
$book_2->appendChild($id_2);
$dom->appendChild($books);
print_r ($dom->saveXML());
<books xmlns:ns="www.example.com/libraryns/1.0">
<book>
<name>PHP - An Introduction</name>
<price>$5.95</price>
<id version="1.0">1</id>
</book>
<ns:book>
<ns:name><![CDATA[PHP - Advanced]]></ns:name>
<ns:price>$25.00</ns:price>
<ns:id>2</ns:id>
</ns:book>
</books>
Similarly to the SimpleXML, you can use DOMDocument to parse XML from a string or from a XML file
1. From a string
$doc->loadXML($string);
2. From a file
Example of parsing
<books>
<book>
<name>PHP - An Introduction</name>
<price>$5.95</price>
<id>1</id>
</book>
<book>
<name>PHP - Advanced</name>
<price>$25.00</price>
<id>2</id>
</book>
</books>
$books = $doc->getElementsByTagName('book');
$title = $book->getElementsByTagName('name')->item(0)->nodeValue;
$price = $book->getElementsByTagName('price')->item(0)->nodeValue;
$id = $book->getElementsByTagName('id')->item(0)->nodeValue;
print_r ("The title of the book $id is $title and it costs $price." . "\n");
SimpleXML is a powerful library which converts XML strings to an easy to use PHP object.
<document>
<book>
<bookAuthor>PHP Programmer</bookAuthor>
</book>
<book>
<bookAuthor>PHP Programmer</bookAuthor>
<bookAuthor>FooBar</bookAuthor>
</book>
</document>
To get started, we need to read our data into SimpleXML. We can do this in 3 different ways. Firstly, we
can load our
$xmlElement = simplexml_import_dom($domNode);
$xmlElement = simplexml_load_file($filename);
<document>
<book>
<bookAuthor>PHP Programmer</bookAuthor>
</book>
<book>
<bookAuthor>PHP Programmer</bookAuthor>
<bookAuthor>FooBar</bookAuthor>
</book>
</document>';
$xmlElement = simplexml_load_string($xmlString);
Whether you've picked to load from a DOM Element, from a file or from a string, you are now left with
a
SimpleXMLElement variable called $xmlElement. Now, we can start to make use of our XML in PHP.
The simplest way to access data in our SimpleXMLElement object is to call the properties directly. If
we want to
access our first bookName, StackOverflow SimpleXML Example, then we can access it as per below.
echo $xmlElement->book->bookName;
At this point, SimpleXML will assume that because we have not told it explicitly which book we want,
that we want
the first one. However, if we decide that we do not want the first one, rather that we want Another
SimpleXML
echo $xmlElement->book[1]->bookName;
It is worth noting that using [0] works the same as not using it, so
$xmlElement->book
$xmlElement->book[0]
There are many reasons you may wish to loop through XML, such as that you have a number of items,
books in our
case, that we would like to display on a webpage. For this, we can use a foreach loop or a standard for
loop, taking
advantage of SimpleXMLElement's count function..
echo $thisBook->bookName
or
$count = $xmlElement->count();
echo $xmlElement->book[$i]->bookName;
Handling Errors
Now we have come so far, it is important to realise that we are only humans, and will likely encounter
an error
eventually - especially if we are playing with different XML files all the time. And so, we will want to
handle those
errors.
Consider we created an XML file. You will notice that while this XML is much alike what we had earlier,
the problem
with this XML file is that the final closing tag is /doc instead of /document.
<document>
<book>
<bookAuthor>PHP Programmer</bookAuthor>
</book>
<book>
<bookAuthor>FooBar</bookAuthor>
</book>
</doc>
libxml_use_internal_errors(true);
$xmlElement = simplexml_load_file($file);
$errors = libxml_get_errors();
switch ( $thisError->level ) {
case LIBXML_ERR_FATAL:
break;
case LIBXML_ERR_ERROR:
break;
case LIBXML_ERR_WARNING:
break;
libxml_clear_errors();
} else {
FATAL ERROR: 76
Message: Opening and ending tag mismatch: document line 2 and doc
Line: 13
Column: 10
File: filepath/filename.xml
However as soon as we fix this problem, we are presented with "Happy Days".
Next open the file to which you want to write. For example, to write to
/var/www/example.com/xml/output.xml,
use:
$xml->openUri('file:///var/www/example.com/xml/output.xml');
$xml->startDocument('1.0', 'utf-8');
$xml->writeElement('foo', 'bar');
<foo>bar</foo>
If you need something a little more complex than simply nodes with plain values, you can also "start"
an element
$xml->startElement('foo');
$xml->writeAttribute('bar', 'baz');
$xml->writeCdata('Lorem ipsum');
$xml->endElement();
1. From a string
$xml_obj = simplexml_load_string($string);
2. From a file
$xml_obj = simplexml_load_file('books.xml');
Example of parsing
<books>
<book>
<name>PHP - An Introduction</name>
<price>$5.95</price>
<id>1</id>
</book>
<book>
<name>PHP - Advanced</name>
<price>$25.00</price>
<id>2</id>
</book>
</books>
$xml = simplexml_load_string($xml_string);
$books = $xml->book;
$id = $book->id;
$title = $book->name;
$price = $book->price;
print_r ("The title of the book $id is $title and it costs $price." . "\n");
Note that or not || must be used here because the precedence of or is higher than =. The code after or
will only be
$xml = simplexml_load_string("filePath.xml");
$xml = simplexml_load_string("https://example.com/doc.xml");
The URL can be of any schemes that PHP supports, or custom stream wrappers.
PHP implements a DOM Level 2 compliant parser, allowing you to work with HTML using familiar
methods like
getElementById() or appendChild().
libxml_use_internal_errors(true);
$doc->loadHTML($html);
echo $doc->getElementById("text")->textContent;
Outputs:
Hello, World!
Note that PHP will emit warnings about any problems with the HTML, especially if you are importing a
document
fragment. To avoid these warnings, tell the DOM library (libxml) to handle its own errors by calling
libxml_use_internal_errors() before importing your HTML. You can then use libxml_get_errors() to
handle
errors if needed.
$doc->loadHTML($html);
$span = $xpath->query("//span[@class='text']")->item(0);
echo $span->textContent;
Outputs:
Hello, World!
Presentation
SimpleXML is a PHP library which provides an easy way to work with XML documents (especially
reading and
$xmlstr = file_get_contents('library.xml');
$library = simplexml_load_string($xmlstr);
$library = simplexml_load_file('library.xml');
// You can load a local file path or a valid URL (if allow_url_fopen is set to "On" in php.ini
Parsing XML using OOP approach
// $isPathToFile: it informs the constructor that the 1st argument represents the path to a file,
$xmlstr = file_get_contents('library.xml');
// $isPathToFile: it informs the constructor that the first argument represents the path to a file,
When SimpleXML parses an XML document, it converts all its XML elements, or nodes, to properties
of the
In addition, it converts XML attributes to an associative array that may be accessed from the property
to
echo $book['isbn'];
echo $book->title;
echo $book->author;
echo $book->publisher;
The major drawback of this approach is that it is necessary to know the names of every element and
attribute in the XML document.
When you don't know their names (or you don't want to know them):
echo $child->getName();
// Get children
(regexp/PCRE)
Parameter Details
A global RegExp match can be performed using preg_match_all. preg_match_all returns all matching
results in the
subject string (in contrast to preg_match, which only returns the first one).
The preg_match_all function returns the number of matches. Third parameter $matches will contain
matches in
If given an array, $matches will contain array in similar format you’d get with preg_match, except that
preg_match
stops at first match, where preg_match_all iterates over the string until the string is wholly consumed
and returns
result of each iteration in a multidimensional array, which format can be controlled by the flag in
fourth argument.
The fourth argument, $flags, controls structure of $matches array. Default mode is
PREG_PATTERN_ORDER and
$pattern = '/[a-z]([0-9])[a-z]/';
var_dump($matches);
var_dump($matches);
var_dump($matches);
array(3) {
[0]=>
array(2) {
[0]=>
string(3) "a1b"
[1]=>
string(1) "1"
[1]=>
array(2) {
[0]=>
string(3) "c2d"
[1]=>
string(1) "2"
[2]=>
array(2) {
[0]=>
string(3) "f4g"
[1]=>
string(1) "4"
$matches has three nested arrays. Each array represents one match, which has the same format as the
return
result of preg_match.
array(2) {
[0]=>
array(3) {
[0]=>
string(3) "a1b"
[1]=>
string(3) "c2d"
[2]=>
string(3) "f4g"
[1]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "4"
When the same regexp is run through preg_match, following array is returned:
array(2) {
[0] =>
string(3) "a1b"
[1] =>
string(1) "1"
var_dump($isMatched); // bool(true)
If you pass in a third parameter, it will be populated with the matching data of the regular expression:
$matches);
$matches contains an array of the whole match then substrings in the regular expression bounded by
parentheses,
in the order of open parenthesis's offset. That means, if you have /z(a(b))/ as the regular expression,
index 0
contains the whole substring zab, index 1 contains the substring bounded by the outer parentheses ab
and index 2
// + : One or more of 0 to 9
//Or
// [] : Character class
// \d : Any digit
Output:
Array
To split a string into a array simply pass the string and a regexp for preg_split(); to match and search,
adding a
third parameter (limit) allows you to set the number of "matches" to perform, the remaining string
will be added
The fourth parameter is (flags) here we use the PREG_SPLIT_NO_EMPTY which prevents our array
from containing
$string = "a;b;c\nd;e;f";
// $1, $2 and $3 represent the first, second and third capturing groups
Outputs
c;b;a
f;e;d
preg_replace_callback works by sending every matched capturing group to the defined callback and
replaces it
with the return value of the callback. This allows us to replace strings based on any kind of logic.
$subject = "He said 123abc, I said 456efg, then she said 789hij";
$regex = "/\b(\d+)\w+/";
// This function replaces the matched entries conditionally
function regex_replace($matches){
switch($matches[1][0]){
case '7':
$replacement = "<b>{$matches[0]}</b>";
break;
default:
$replacement = "<i>{$matches[0]}</i>";
return $replacement;
print_r($replaced_str);
PHP only allows single inheritance. In other words, a class can only extend one other class. But what if
you need to
include something that doesn't belong in the parent class? Prior to PHP 5.4 you would have to get
creative, but in
5.4 Traits were introduced. Traits allow you to basically "copy and paste" a portion of a class into your
main class
trait Talk {
echo $this->phrase;
use Talk;
$this->speak();
$this->phrase = $phrase;
So here we have MrEd, which is already extending Horse. But not all horses Talk, so we have a Trait for
that. Let's
First, we define our Trait. We can use it with autoloading and Namespaces (see also Referencing a class
or function
in a namespace). Then we include it into our MrEd class with the keyword use.
You'll note that MrEd takes to using the Talk functions and variables without defining them.
Remember what we
said about copy and paste? These functions and variables are all defined within the class now, as if this
class had
defined them.
Traits are most closely related to Abstract classes in that you can define variables and functions. You
also cannot
instantiate a Trait directly (i.e. new Trait()). Traits cannot force a class to implicitly define a function
like an
Abstract class or an Interface can. Traits are only for explicit definitions (since you can implement as
many
The first thing you should do, when considering a Trait, is to ask yourself this important question
More often than not, the answer is going to be Yes. Traits are edge cases caused by single inheritance.
The
temptation to misuse or overuse Traits can be high. But consider that a Trait introduces another source
for your
code, which means there's another layer of complexity. In the example here, we're only dealing with 3
classes. But
Traits mean you can now be dealing with far more than that. For each Trait, your class becomes that
much harder
to deal with, since you must now go reference each Trait to find out what it defines (and potentially
where a
collision happened, see Conflict Resolution). Ideally, you should keep as few Traits in your code as
possible.
interface Logger {
function log($message);
Now say we have two concrete implementations of the Logger interface: the FileLogger and the
ConsoleLogger.
Now if you define some other class Foo which you also want to be able to perform logging tasks, you
could do
private $logger;
$this->logger = $logger;
if ($this->logger) {
$this->logger->log($message);
Foo is now also a Logger, but its functionality depends on the Logger implementation passed to it via
setLogger().
If we now want class Bar to also have this logging mechanism, we would have to duplicate this piece
of logic in the
Bar class.
trait LoggableTrait {
protected $logger;
$this->logger = $logger;
if ($this->logger) {
$this->logger->log($message);
Now that we have defined the logic in a trait, we can use the trait to add the logic to the Foo and Bar
classes:
class Foo {
use LoggableTrait;
class Bar {
use LoggableTrait;
And, for example, we can use the Foo class like this:
//note how we use the trait as a 'proxy' to call the Logger's log method on the Foo instance
$foo->log('my beautiful message');
Trying to use several traits into one class could result in issues involving conflicting methods. You need
to resolve
trait MeowTrait {
trait WoofTrait {
use WoofTrait;
use MeowTrait;
Fatal error: Trait method say has not been applied, because there are collisions with other trait
methods
on TalkingParrot
use keyword insteadof to use the method from one trait instead of method from another trait
create an alias for the method with a construct like WoofTrait::say as sayAsDog;
WoofTrait::say as sayAsDog;
$talkingParrot->say();
$talkingParrot->sayAsDog();
Meow
Woof
Disclaimer: In no way does this example advocate the use of singletons. Singletons are to be used with
a lot of care.
In PHP there is quite a standard way of implementing a singleton:
private $instance;
if (!self::$instance) {
return self::$instance;
To prevent code duplication, it is a good idea to extract this behaviour into a trait.
trait SingletonTrait {
private $instance;
if (!self::$instance) {
// new self() will refer to the class that uses the trait
return self::$instance;
Now any class that wants to function as a singleton can simply use the trait:
class MyClass {
use SingletonTrait;
$myClass = MyClass::getInstance();
Even though it is now impossible to serialize a singleton, it is still useful to also disallow the deserialize
method.
Over time, our classes may implement more and more interfaces. When these interfaces have many
methods, the
interface Printable {
interface Cacheable {
//interface methods
Instead of implementing all the interface methods inside the Article class, we could use separate Traits
to
implement these interfaces, keeping the class smaller and separating the code of the interface
From example, to implement the Printable interface we could create this trait:
trait PrintableArticle {
}
and make the class use the trait:
use PrintableArticle;
use CacheableArticle;
The primary benefits would be that our interface-implementation methods will be separated from the
rest of the
class, and stored in a trait who has the sole responsibility to implement the interface for that
particular type
of object.
trait Hello {
trait World {
echo 'World';
class MyHelloWorld {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
Hello World!
trait HelloWorld {
class MyClass1 {
class MyClass2 {
(new MyClass1())->sayHello();
// Fatal error: Uncaught Error: Call to protected method MyClass1::sayHello()
(new MyClass2())->myPrivateHello();
(new MyClass2())->sayHello();
// Hello World!
So be aware that in the last example in MyClass2 the original un-aliased method from trait HelloWorld
stays
accessible as-is.
Manager
Parameter Details
license Defines the type of license you want to use in the Project.
authors Defines the authors of the project, as well as the author details.
support Defines the support emails, irc channel, and various links.
suggest Defines the package suggestions, i.e. packages which can help if installed.
Composer is PHP's most commonly used dependency manager. It's analogous to npm in Node, pip for
Python, or
Composer is a dependency/package manager for PHP. It can be used to install, keep track of, and
update your
project dependencies. Composer also takes care of autoloading the dependencies that your
application relies on,
letting you easily use the dependency inside your project without worrying about including them at
the top of any
given file.
Dependencies for your project are listed within a composer.json file which is typically located in your
project root.
This file holds information about the required versions of packages for production and also
development.
A full outline of the composer.json schema can be found on the Composer Website.
This file can be edited manually using any text-editor or automatically through the command line via
commands
To start using composer in your project, you will need to create the composer.json file. You can either
create it
manually or simply run composer init. After you run composer init in your terminal, it will ask you for
some basic
information about your project: Package name (vendor/package - e.g. laravel/laravel), Description -
optional,
Author and some other information like Minimum Stability, License and Required Packages.
The require key in your composer.json file specifies Composer which packages your project depends
on. require
takes an object that maps package names (e.g. monolog/monolog) to version constraints (e.g. 1.0.*).
"require": {
"composer/composer": "1.2.*"
To install the defined dependencies, you will need to run the composer install command and it will
then find the
defined packages that matches the supplied version constraint and download it into the vendor
directory. It's a
You will notice the install command also created a composer.lock file.
A composer.lock file is automatically generated by Composer. This file is used to track the currently
installed
versions and state of your dependencies. Running composer install will install packages to exactly the
state
While composer provides a system to manage dependencies for PHP projects (e.g. from Packagist), it
can also
notably serve as an autoloader, specifying where to look for specific namespaces or include generic
function files.
// ...
"autoload": {
"psr-4": {
"MyVendorName\\MyProject": "src/"
},
"files": [
"src/functions.php"
},
"autoload-dev": {
"psr-4": {
"MyVendorName\\MyProject\\Tests": "tests/"
This configuration code ensures that all classes in the namespace MyVendorName\MyProject are
mapped to the src
directory and all classes in MyVendorName\MyProject\Tests to the tests directory (relative to your
root directory). It
After putting this in your composer.json file, run composer update in a terminal to have composer
update the
dependencies, the lock file and generate the autoload.php file. When deploying to a production
environment you
would use composer install --no-dev. The autoload.php file can be found in the vendor directory which
should
You should require this file early at a setup point in the lifecycle of your application using a line similar
to that
below.
Once included, the autoload.php file takes care of loading all the dependencies that you provided in
your
composer.json file.
MyVendorName\MyProject\Shapes\Square ➔ src/Shapes/Square.php.
MyVendorName\MyProject\Tests\Shapes\Square ➔ tests/Shapes/Square.php.
composer update
composer update will update our dependencies as they are specified in composer.json.
"require": {
"laravelcollective/html": "2.0.*"
Supposing we have actually installed the 2.0.1 version of the package, running composer update will
cause an
upgrade of this package (for example to 2.0.2, if it has already been released).
Read composer.json
composer install
composer install will install all of the dependencies as specified in the composer.lock file at the version
specified
In detail:
composer update is mostly used in the 'development' phase, to upgrade our project packages.
composer install is primarily used in the 'deploying phase' to install our application on a production
server
or on a testing environment, using the same dependencies stored in the composer.lock file created by
composer update.
Command Usage
install Installs the project dependencies from the composer.lock file if present, or falls back on the
composer.json.
licenses Show information about licenses of dependencies
outdated Shows a list of installed packages that have updates available, including their latest version.
prohibits Shows which packages prevent the given package from being installed
update Updates your dependencies to the latest version according to composer.json, and updates the
composer.lock file.
why-not Shows which packages prevent the given package from being installed
Composer tracks which versions of packages you have installed in a file called composer.lock, which is
intended to
be committed to version control, so that when the project is cloned in the future, simply running
composer install
Composer deals with PHP dependencies on a per-project basis. This makes it easy to have several
projects on one
Composer provides an autoloader, making it extremely easy to get started with any package. For
instance, after
installing Goutte with composer require fabpot/goutte, you can immediately start to use Goutte in a
new project:
<?php
Composer allows you to easily update a project to the latest version that is allowed by your
composer.json. EG.
composer update fabpot/goutte, or to update each of your project's dependencies: composer update.
You may install Composer locally, as part of your project, or globally as a system wide executable.
Locally
# to check the validity of the downloaded installer, check here against the SHA-384:
# https://composer.github.io/pubkeys.html
php composer-setup.php
php -r "unlink('composer-setup.php');"
This will download composer.phar (a PHP Archive file) to the current directory. Now you can run php
Globally
To use Composer globally, place the composer.phar file to a directory that is part of your PATH
mv composer.phar /usr/local/bin/composer
Now you can use composer anywhere instead of php composer.phar, e.g.
composer install
__call() and __callStatic() are called when somebody is calling nonexistent object method in object or
static
context.
class Foo
/**
* This method will be called when somebody will try to invoke a method in object
* $foo->method($arg, $arg1);
* First argument will contain the method name(in example above it will be "method"),
* and the second will contain the values of $arg and $arg1 as an array.
*/
// or something generic.
// is a valid name or
$snakeName = CaseHelper::camelToSnake($method);
switch ($subMethod) {
case "get":
return $this->data[$propertyName];
case "set":
$this->data[$propertyName] = $arguments[0];
break;
case "has":
return isset($this->data[$propertyName]);
default:
/**
* __callStatic will be called from static content, that is, when calling a nonexistent
* static method:
*
* Foo::buildSomethingCool($arg);
* First argument will contain the method name(in example above it will be "buildSomethingCool"),
* Note that signature of this method is different(requires static keyword). This method was not
*/
// This method can be used when you need something like generic factory
// or something else(to be honest use case for this is not so clear to me).
print_r(func_get_args());
Example:
$instance->setSomeState("foo");
var_dump($instance->hasSomeState()); // bool(true)
Foo::exampleStaticCall("test");
// outputs:
Array
(
Whenever you attempt to retrieve a certain field from a class like so:
$height = $animal->height;
PHP invokes the magic method __get($name), with $name equal to "height" in this case. Writing to a
class field like
so:
$animal->height = 10;
Will invoke the magic method __set($name, $value), with $name equal to "height" and $value equal
to 10.
PHP also has two built-in functions isset(), which check if a variable exists, and unset(), which destroys
a variable.
isset($animal->height);
Will invoke the __isset($name) function on that object. Destroying a variable like so:
unset($animal->height);
Normally, when you don't define these methods on your class, PHP just retrieves the field as it is
stored in your
class. However, you can override these methods to create classes that can hold data like an array, but
are usable
like an object:
class Example {
private $data = [];
$this->data[$name] = $value;
if (!array_key_exists($name, $this->data)) {
return null;
return $this->data[$name];
return isset($this->data[$name]);
unset($this->data[$name]);
$example->a = 15;
if (isset($example->a)) {
unset($example->a));
Note that calling empty() on a class attribute will invoke __isset() because as the PHP manual states:
__construct() is the most common magic method in PHP, because it is used to set up a class when it is
initialized.
The opposite of the __construct() method is the __destruct() method. This method is called when
there are no
more references to an object that you created or when you force its deletion. PHP's garbage collection
will clean up
the object by first calling its destructor and then removing it from memory.
class Shape {
public $width;
public $height;
parent::__construct();
$this->width = $width;
$this->height = $height;
function createRectangle() {
// Instantiating an object will call the constructor with the specified arguments
createRectangle();
// When the function scope is exited, the object is destroyed and its
// destructor is called.
Whenever an object is treated as a string, the __toString() method is called. This method should return
a string
class User {
public $first_name;
public $last_name;
public $age;
$user->first_name = "Chuck";
$user->last_name = "Norris";
$user->age = 76;
__clone is invoked by use of the clone keyword. It is used to manipulate object state upon cloning,
after the object
class CloneableUser
public $name;
public $lastName;
/**
* This method will be invoked by a clone operator and will prepend "Copy " to the
*/
Example:
$user1->name = "John";
$user1->lastName = "Doe";
This magic method is called when user tries to invoke object as a function. Possible use cases may
include some
class Invokable
/**
* $invokable();
*
*/
print_r(func_get_args());
// Example:
$invokable([1, 2, 3]);
// optputs:
Array
[0] => 1
[1] => 2
[2] => 3
__sleep and __wakeup are methods that are related to the serialization process. serialize function
checks if a
class has a __sleep method. If so, it will be executed before any serialization. __sleep is supposed to
return an
__wakeup in turn will be executed by unserialize if it is present in class. It's intention is to re-establish
resources
and other things that are needed to be initialized upon unserialization.
class Sleepy {
public $tableName;
public $tableFields;
public $dbConnection;
/**
*/
/**
* For sake of example, lets assume that $this->c, which was not serialized,
*/
// $this->dbConnection
$this->dbConnection = DB::connect();
}
This method is called by var_dump() when dumping an object to get the properties that should be
shown.
If the method isn't defined on an object, then all public, protected and private properties will be
shown.
— PHP Manual
class DeepThought {
return [42];
Version ≤ 5.6
var_dump(new DeepThought());
Version ≥ 5.6
var_dump(new DeepThought());
int(42)
}
GoalKicker.com – PHP Notes for Professionals 238
Parameter Description
use_include_path You can use the optional second parameter and set it to TRUE, if you want to search
for the file
Raw direct IO
file_get_contents and file_put_contents provide the ability to read/write from/to a file to/from a PHP
string in a
single call.
file_put_contents can also be used with the FILE_APPEND bitmask flag to append to, instead of
truncate and
overwrite, the file. It can be used along with LOCK_EX bitmask to acquire an exclusive lock to the file
while
proceeding to writing. Bitmask flags can be joined with the | bitwise-OR operator.
$path = "file.txt";
$contents = file_get_contents($path);
file_put_contents($path, $contents);
FILE_APPEND is handy for appending to log files while LOCK_EX helps prevent race condition of file
writing from
multiple processes. For example, to write to a log file about the current session:
CSV IO
The fgetcsv parses line from open file checking for csv fields. It returns CSV fields in an array on success
or FALSE
on failure.
$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
print_r(fgetcsv($file,5," "));
fclose($file);
contacts.csv
Output:
Array
Array
(
[0] => Hege,
readfile copies a file to the output buffer. readfile() will not present any memory issues, even when
sending large
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Type: application/octet-stream');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
readfile($file);
exit;
Alternatively, to seek a point in the file to start copying to stdout, use fpassthru instead. In the
following example,
fpassthru($fh);
print_r(file("test.txt"));
test.txt
Output:
Array
Deleting files
The unlink function deletes a single file and returns whether the operation was successful.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
To delete a directory with files, delete the files in the directories first. If the directory contains
subdirectories,
The following example scans files in a directory, deletes member files/directories recursively, and
returns the
$count = 0;
// ensure that $dir ends with a slash so that we can concatenate it with the filenames directly
$list = dir($dir);
// store the next file name to $file. if $file is false, that's all -- end the loop.
if(is_file($dir . $file)) {
unlink($dir . $file);
$count++;
} elseif(is_dir($dir . $file)) {
rmdir($dir);
return $count;
}
The is_dir function returns whether the argument is a directory, while is_file returns whether the
argument is a
$dir = "/this/is/a/directory";
$file = "/this/is/a/file.txt";
This gives:
/this/is/a/directory is a directory
/this/is/a/directory exists
/this/is/a/file.txt is a file
/this/is/a/file.txt exists
fifo
char
dir
block
link
file
socket
unknown
Note that filetype returns false and triggers an E_WARNING if the file doesn't exist.
Passing the filename to the is_writable and is_readable functions check whether the file is writable or
readable
respectively.
The functions return false gracefully if the file does not exist.
Using filemtime and fileatime returns the timestamp of the last modification or access of the file. The
return
value is a Unix timestamp -- see Working with Dates and Time for details.
$fileToAnalyze = ('/var/www/image.png');
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
Array
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
Parameter Details
PATHINFO_FILENAME]
If an option (the second parameter) is not passed, an associative array is returned otherwise a string is
returned.
Simply parses the string into parts. No validation is done on the file (no mime-type checking, etc.)
The extension is simply the last extension of $path The path for the file image.jpg.png would be .png
even if
it technically a .jpg file. A file without an extension will not return an extension element in the array.
Section 43.4: Stream-based file IO
Opening a stream
fopen opens a file stream handle, which can be used with various functions for reading, writing,
seeking and other
functions on top of it. This value is of resource type, and cannot be passed to other threads persisting
its
functionality.
Mode Description
r+ Open for reading and writing, starting at the beginning of the file
open for writing only, starting at the beginning of the file. If the file exists it will empty the file. If it
doesn't
w+ open for reading and writing, starting at the beginning of the file. If the file exists it will empty the
file. If it
a open a file for writing only, starting at the end of the file. If the file does not exist, it will try to create
it
a+ open a file for reading and writing, starting at the end of the file. If the file does not exist, it will try
to create
it
x create and open a file for writing only. If the file exists the fopen call will fail
x+ create and open a file for reading and writing. If the file exists the fopen call will fail
c
open the file for writing only. If the file does not exist it will try to create it. It will start writing at the
beginning of the file, but will not empty the file ahead of writing
c+ open the file for reading and writing. If the file does not exist it will try to create it. It will start
writing at the
beginning of the file, but will not empty the file ahead of writing
Adding a t behind the mode (e.g. a+b, wt, etc.) in Windows will translate "\n" line endings to "\r\n"
when working
with the file. Add b behind the mode if this is not intended, especially if it is a binary file.
The PHP application should close streams using fclose when they are no longer used to prevent the
Too many
open files error. This is particularly important in CLI programs, since the streams are only closed when
the
runtime shuts down -- this means that in web servers, it may not be necessary (but still should, as a
practice to
prevent resource leak) to close the streams if you do not expect the process to run for a long time, and
will not
Reading
Using fread will read the given number of bytes from the file pointer, or until an EOF is met.
Reading lines
Using fgets will read the file until an EOL is reached, or the given length is read.
Both fread and fgets will move the file pointer while reading.
Using stream_get_contents will all remaining bytes in the stream into a string and return it.
Initially after opening the stream, the file pointer is at the beginning of the file (or the end, if the mode
a is used).
Using the fseek function will move the file pointer to a new position, relative to one of three values:
SEEK_SET: This is the default value; the file position offset will be relative to the beginning of the file.
SEEK_CUR: The file position offset will be relative to the current position.
SEEK_END: The file position offset will be relative to the end of the file. Passing a negative offset is the
most
common use for this value; it will move the file position to the specified number of bytes before the
end of
file.
Using ftell will show the absolute position of the file pointer.
For example, the following script reads skips the first 10 bytes, reads the next 10 bytes, skips 10 bytes,
reads the
fclose($fh);
Writing
Using fwrite writes the provided string to the file starting at the current file pointer.
Copying files
copy copies the source file in the first argument to the destination in the second argument. The
resolved
if (copy('test.txt', 'dest.txt')) {
} else {
Copying directories is pretty much similar to deleting directories, except that for files copy instead of
unlink is used,
while for directories, mkdir instead of rmdir is used, at the beginning instead of being at the end of the
function.
$count = 0;
// ensure that $src and $dest end with a slash so that we can concatenate it with the filenames
directly
$list = dir($src);
@mkdir($dest);
// store the next file name to $file. if $file is false, that's all -- end the loop.
if(is_file($src . $file)) {
copy($src . $file, $dest . $file);
$count++;
} elseif(is_dir($src . $file)) {
return $count;
Renaming/Moving
Renaming/Moving files and directories is much simpler. Whole directories can be moved or renamed
in a single call,
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");
files
If we need to parse a large file, e.g. a CSV more than 10 Mbytes containing millions of rows, some use
file or
error. Consider the following source (top-1m.csv has exactly 1 million rows and is about 22 Mbytes of
size)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
This outputs:
int(262144)
int(210501632)
because the interpreter needed to hold all the rows in $arr array, so it consumed ~200 Mbytes of
RAM. Note that
var_dump(memory_get_usage(true));
$index = 1;
FILE_APPEND);
$index++;
fclose($handle);
var_dump(memory_get_usage(true));
which outputs
int(262144)
int(262144)
so we don't use a single extra byte of memory, but parse the whole CSV and save it to another file
reversing the
value of the 2nd column. That's because fgetcsv reads only one row and $row is overwritten in every
loop.
The example below shows a simple stream wrapper that sends PATCH HTTP requests when the stream
is closed.
registered");
class FooWrapper {
// this will be modified by PHP to show the context passed in the current call.
public $context;
private $url;
// when fopen() with a protocol for this wrapper is called, this method can be implemented to
public function stream_open(string $path, string $mode, int $options, string &$openedPath) :
bool {
$url = parse_url($path);
return true;
return strlen($data);
curl_exec($curl);
curl_close($curl);
$this->buffer = "";
$url = parse_url($path);
curl_exec($curl);
curl_close($curl);
}
This example only shows some examples of what a generic stream wrapper would contain. These are
not all
methods available. A full list of methods that can be implemented can be found at
http://php.net/streamWrapper.
<?php
class Student
class School
<?php
enroll($chris, $edinburgh);
The self keyword can be used as a type hint to indicate that the value must be an instance of the class
that
Support for type hinting array parameters (and return values after PHP 7.1) was added in PHP 5.1 with
the keyword
array. Any arrays of any dimensions and types, as well as empty arrays, are valid values.
Support for type hinting callables was added in PHP 5.4. Any value that is_callable() is valid for
parameters and
return values hinted callable, i.e. Closure objects, function name strings and array(class_name|object,
method_name).
If a typo occurs in the function name such that it is not is_callable(), a less obvious error message
would be
displayed:
Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be of the type callable, string/array
given
foo("count"); // valid
foo("Phar::running"); // valid
Nonstatic methods can also be passed as callables in static format, resulting in a deprecation warning
and level
to the callable provided, it will end up as if the method does not exist.
class Foo{
$c();
Foo::r(["Foo", "f"]);
r(["Foo", "f"]);
Output:
Fatal error: Uncaught TypeError: Argument 1 passed to r() must be callable, array given
Support for type hinting scalar types was added in PHP 7. This means that we gain type hinting
support for
<?php
return $a + $b;
By default, PHP will attempt to cast any provided argument to match its type hint. Changing the call to
add(1.5, 2)
gives exactly the same output, since the float 1.5 was cast to int by PHP.
To stop this behavior, one must add declare(strict_types=1); to the top of every PHP source file that
requires it.
<?php
declare(strict_types=1);
return $a + $b;
var_dump(add(1.5, 2));
Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type integer, float given
Some PHP functions may return a value of type resource. Since this is not a scalar type, but a special
type, it is not
As an example, curl_init() will return a resource, as well as fopen(). Of course, those two resources
aren't
compatible to each other. Because of that, PHP 7 will always throw the following TypeError when type
hinting
resource explicitly:
Parameters
Nullable type hint was added in PHP 7.1 using the ? operator before the type hint.
g(null); // TypeError: Argument 1 passed to g() must be of the type string, null given
Before PHP 7.1, if a parameter has a type hint, it must declare a default value null to accept null
values.
f(null); // valid
g(null); // TypeError: Argument 1 passed to g() must be of the type string, null given
Return values
In PHP 7.0, functions with a return type must not return null.
In PHP 7.1, functions can declare a nullable return type hint. However, the function must still return
null, not void
return null;
f(); // OK
g(); // TypeError: Return value of g() must be of the type string or null, none returned
h(); // TypeError: Return value of h() must be of the type string or null, none returned
Since PHP objects don't inherit from any base class (including stdClass), there is no support for type
hinting a
<?php
function doSomething(object $obj) {
return $obj;
class ClassOne {}
class ClassTwo {}
doSomething($classOne);
doSomething($classTwo);
Fatal error: Uncaught TypeError: Argument 1 passed to doSomething() must be an instance of object,
A workaround to this is to declare a degenerate interface that defines no methods, and have all of
your objects
<?php
interface Object {}
return $obj;
doSomething($classOne);
doSomething($classTwo);
In PHP 7.1, the void return type was added. While PHP has no actual void value, it is generally
understood across
programming languages that a function that returns nothing is returning void. This should not be
confused with
// valid
Note that if you declare a void return, you cannot return any values or you will get a fatal error:
return null; // Fatal error: A void function must not return a value
return; // valid
Parameter Details
variable Value to filter. Note that scalar values are converted to string internally before they are
filtered.
------ ------
filter
The ID of the filter to apply. The Types of filters manual page lists the available filters.If omitted,
------ ------
options
Associative array of options or bitwise disjunction of flags. If filter accepts options, flags can be
provided in "flags" field of array. For the "callback" filter, callable type should be passed. The callback
must accept one argument, the value to be filtered, and return the value after filtering/sanitizing it.
This extension filters data by either validating or sanitizing it. This is especially useful when the data
source contains
unknown (or foreign) data, like user supplied input. For example, this data may come from an HTML
form.
var_dump(filter_var(1.0, FILTER_VALIDATE_FLOAT));
var_dump(filter_var(1.0000, FILTER_VALIDATE_FLOAT));
var_dump(filter_var(1.00001, FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.0', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.0000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.00001', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.0', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.0000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.00001', FILTER_VALIDATE_FLOAT));
float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
float(1)
float(1.00001)
bool(false)
bool(false)
bool(false)
bool(false)
float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
float(1)
float(1.00001)
float(1000)
float(1000)
float(1000)
float(1000.00001)
Section 46.3: Validate A MAC Address
var_dump(filter_var('FA-F9-DD-B2-5E-0D', FILTER_VALIDATE_MAC));
var_dump(filter_var('DC-BB-17-9A-CE-81', FILTER_VALIDATE_MAC));
var_dump(filter_var('96-D5-9E-67-40-AB', FILTER_VALIDATE_MAC));
var_dump(filter_var('96-D5-9E-67-40', FILTER_VALIDATE_MAC));
var_dump(filter_var('', FILTER_VALIDATE_MAC));
Results:
string(17) "FA-F9-DD-B2-5E-0D"
string(17) "DC-BB-17-9A-CE-81"
string(17) "96-D5-9E-67-40-AB"
bool(false)
bool(false)
var_dump(filter_var('john@example.com', FILTER_SANITIZE_EMAIL));
var_dump(filter_var("!#$%&'*+-=?^_`{|}~.[]@example.com", FILTER_SANITIZE_EMAIL));
var_dump(filter_var('john/@example.com', FILTER_SANITIZE_EMAIL));
var_dump(filter_var('john\@example.com', FILTER_SANITIZE_EMAIL));
Results:
string(16) "john@example.com"
string(33) "!#$%&'*+-=?^_`{|}~.[]@example.com"
string(16) "john@example.com"
string(16) "john@example.com"
string(16) "john@example.com"
var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(-1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(+1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(+1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(-1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('-1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('+1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('+1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('-1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("!#$%&'*+-=?^_`{|}~@.[]0123456789abcdefghijklmnopqrstuvwxyz",
FILTER_SANITIZE_NUMBER_INT));
Results:
string(1) "1"
string(2) "-1"
string(1) "1"
string(1) "1"
string(1) "1"
string(2) "-1"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(3) "100"
string(4) "+100"
string(4) "-100"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(12) "+-0123456789"
Sanitze URLs
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_SANITIZE_URL));
var_dump(filter_var("http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-=?^_`{|}~.
[]",
FILTER_SANITIZE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=a b c',
FILTER_SANITIZE_URL));
Results:
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(72) "http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-=?^_`{|}~.[]"
string(53) "http://www.example.com/path/to/dir/index.php?test=abc"
When filtering an email address filter_var() will return the filtered data, in this case the email address,
or false if
var_dump(filter_var('john@example.com', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('notValidEmail', FILTER_VALIDATE_EMAIL));
Results:
string(16) "john@example.com"
bool(false)
This function doesn't validate not-latin characters. Internationalized domain name can be validated in
their xn--
form.
Note that you cannot know if the email address is correct before sending an email to it. You may want
to do some
extra checks such as checking for a MX record, but this is not necessary. If you send a confirmation
email, don't
When filtering a value that should be an integer filter_var() will return the filtered data, in this case
the integer,
var_dump(filter_var('10', FILTER_VALIDATE_INT));
var_dump(filter_var('a10', FILTER_VALIDATE_INT));
var_dump(filter_var('10a', FILTER_VALIDATE_INT));
var_dump(filter_var('10,000', FILTER_VALIDATE_INT));
var_dump(filter_var('-5', FILTER_VALIDATE_INT));
var_dump(filter_var('+7', FILTER_VALIDATE_INT));
Results:
int(10)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
int(-5)
int(7)
If you are expecting only digits, you can use a regular expression:
else
// entry is incorrect
If you convert this value into an integer, you don't have to do this check and so you can use filter_var.
When validating that an integer falls in a range the check includes the minimum and maximum
bounds:
$options = array(
'min_range' => 5,
'max_range' => 10,
);
Results:
int(5)
int(10)
int(8)
bool(false)
bool(false)
bool(false)
When filtering a URL filter_var() will return the filtered data, in this case the URL, or false if a valid URL
cannot be
found:
URL: example.com
var_dump(filter_var('example.com', FILTER_VALIDATE_URL));
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
URL: http://example.com
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
Results:
string(18) "http://example.com"
string(18) "http://example.com"
string(18) "http://example.com"
bool(false)
bool(false)
URL: http://www.example.com
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Results:
string(22) "http://www.example.com"
string(22) "http://www.example.com"
string(22) "http://www.example.com"
bool(false)
bool(false)
URL: http://www.example.com/path/to/dir/
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Results:
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
bool(false)
URL: http://www.example.com/path/to/dir/index.php
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Results:
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
bool(false)
URL: http://www.example.com/path/to/dir/index.php?test=y
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Results:
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
Warning: You must check the protocol to protect you against an XSS attack:
var_dump(filter_var('javascript://comment%0Aalert(1)', FILTER_VALIDATE_URL));
// string(31) "javascript://comment%0Aalert(1)"
var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.0, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.0000, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.00001, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.0', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.0000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.00001', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.0', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT));
Results:
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(9) "18281-009"
var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_THOUSAND));
var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_THOUSAND));
var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_THOUSAND));
Results:
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(5) "1,000"
string(6) "1,0000"
string(9) "1,0000000"
string(10) "1,00000001"
string(9) "18281-009"
var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_SCIENTIFIC));
var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_SCIENTIFIC));
var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT,
FILTER_FLAG_ALLOW_SCIENTIFIC));
Results:
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(10) "18281e-009"
Section 46.12: Validate IP Addresses
var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP));
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP));
var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP));
var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP));
Results:
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
string(11) "192.168.0.1"
string(9) "127.0.0.1"
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4));
Results:
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
string(9) "127.0.0.1"
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP,
FILTER_FLAG_IPV6));
Results:
bool(false)
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
bool(false)
bool(false)
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE));
Results:
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
bool(false)
string(9) "127.0.0.1"
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP,
FILTER_FLAG_NO_RES_RANGE));
Results:
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
bool(false)
Example
$string = "<p>Example</p>";
A yield statement is similar to a return statement, except that instead of stopping execution of the
function and
returning, yield instead returns a Generator object and pauses execution of the generator function.
function gen_one_to_three() {
yield $i;
}
You can see that this function returns a Generator object by inspecting the output of var_dump:
var_dump(gen_one_to_three())
# Outputs:
Yielding Values
echo "$value\n";
function gen_one_to_three() {
first: 1
second: 2
third: 3
One common use case for generators is reading a file from disk and iterating over its contents. Below
is a class that
allows you to iterate over a CSV file. The memory usage for this script is very predictable, and will not
fluctuate
<?php
class CsvReader
protected $file;
while (!feof($this->file)) {
yield $row;
}
return;
Generators are useful when you need to generate a large collection to later iterate over. They're a
simpler
$array = [];
return $array;
All this function does is generates an array that's filled with random numbers. To use it, we might do
randomNumbers(10), which will give us an array of 10 random numbers. What if we want to generate
one million
random numbers? randomNumbers(1000000) will do that for us, but at a cost of memory. One million
integers
$startMemory = memory_get_usage();
$randomNumbers = randomNumbers(1000000);
This is due to the entire one million random numbers being generated and returned at once, rather
than one at a
generator
Generators are fast coded and in many cases a slim alternative to heavy iterator-implementations.
With the fast
implementation comes a little lack of control when a generator should stop generating or if it should
generate
something else. However this can be achieved with the usage of the send() function, enabling the
requesting
//Imagining accessing a large amount of data from a server, here is the generator for this:
function generateDataFromServerDemo()
$indexCurrentRun = 0; //In this example in place of data from the server, I just send feedback
$timeout = false;
while (!$timeout)
{
$timeout = yield $indexCurrentRun; // Values are passed to caller. The next time the
generator is called, it will start at this statement. If send() is used, $timeout will take this
value.
$indexCurrentRun++;
foreach($generatorDataFromServer as $numberOfRuns)
else
You should verify every received string as being valid UTF-8 before you try to store it or use it
anywhere.
PHP's mb_check_encoding() does the trick, but you have to use it consistently. There's really no way
around
this, as malicious clients can submit data in whatever encoding they want.
$string = $_REQUEST['user_comment'];
if (!mb_check_encoding($string, 'UTF-8')) {
$actualEncoding = mb_detect_encoding($string);
If you're using HTML5 then you can ignore this last point. You want all data sent to you by browsers to
be
in UTF-8. The only reliable way to do this is to add the accept-charset attribute to all of your <form>
tags like
so:
If your application transmits text to other systems, they will also need to be informed of the character
encoding. In PHP, you can use the default_charset option in php.ini, or manually issue the Content-
Type
MIME header yourself. This is the preferred method when targeting modern browsers.
If you are unable to set the response headers, then you can also set the encoding in an HTML
document with
HTML metadata.
HTML5
<meta charset="utf-8">
This topic specifically talks about UTF-8 and considerations for using it with a database. If you want
more
Specify the utf8mb4 character set on all tables and text columns in your database. This makes MySQL
MySQL will implicitly use utf8mb4 encoding if a utf8mb4_* collation is specified (without any explicit
character set).
Older versions of MySQL (< 5.5.3) do not support utf8mb4 so you'll be forced to use utf8, which only
In your application code (e.g. PHP), in whatever DB access method you use, you'll need to set the
connection
charset to utf8mb4. This way, MySQL does no conversion from its native UTF-8 when it hands data off
to your
Some drivers provide their own mechanism for configuring the connection character set, which both
updates
its own internal state and informs MySQL of the encoding to be used on the connection. This is usually
the
preferred approach.
For Example (The same consideration regarding utf8mb4/utf8 applies as above):
If you're using the PDO abstraction layer with PHP ≥ 5.3.6, you can specify charset in the DSN:
If you're stuck with plain mysql but happen to be running PHP ≥ 5.2.3, you can call mysql_set_charset.
If the database driver does not provide its own mechanism for setting the connection character set,
you may have to issue a query to tell MySQL how your application expects data on the connection to
You can use the following code for going back and forward.
if (!function_exists('codepoint_encode')) {
function codepoint_encode($str) {
if (!function_exists('codepoint_decode')) {
function codepoint_decode($str) {
How to use:
var_dump(codepoint_encode("我好"));
var_dump(codepoint_decode('\\u6211\\u597d'));
Output:
string(12) "\\u6211\\u597d"
string(6) "我好"
You can use the following code for going back and forward.
if (!function_exists('mb_internal_encoding')) {
if (!function_exists('mb_convert_encoding')) {
$to_encoding, $str);
}
}
if (!function_exists('mb_chr')) {
} else {
if (!function_exists('mb_ord')) {
return $ord;
} else {
if (!function_exists('mb_htmlentities')) {
if (!function_exists('mb_html_entity_decode')) {
$encoding);
How to use :
var_dump(mb_chr(50319, 'UCS-4BE'));
var_dump(mb_chr(271));
var_dump(mb_chr(0xC48F, 'UCS-4BE'));
var_dump(mb_chr(0x010F));
var_dump(mb_ord('ď', 'UCS-4BE'));
var_dump(mb_ord('ď'));
var_dump(dechex(mb_ord('ď', 'UCS-4BE')));
var_dump(dechex(mb_ord('ď')));
var_dump(mb_htmlentities('tchüß', false));
var_dump(mb_html_entity_decode('tchüß'));
echo "\nEncode / decode to HEX based HTML entities\n";
var_dump(mb_htmlentities('tchüß'));
var_dump(mb_html_entity_decode('tchüß'));
Output :
string(4) "ď"
string(2) "ď"
string(4) "ď"
string(2) "ď"
int(50319)
int(271)
string(4) "c48f"
string(3) "10f"
string(15) "tchüß"
string(7) "tchüß"
string(15) "tchüß"
string(7) "tchüß"
Native string functions are mapped to single byte functions, they do not work well with Unicode. The
extentions
iconv and mbstring offer some support for Unicode, while the Intl-extention offers full support. Intl is a
wrapper for
the facto de standard ICU library, see http://site.icu-project.org for detailed information that is not
available on
ICU offers full Internationalization of which Unicode is only a smaller part. You can do transcoding
easily:
$url = 'http://www.example.com/page?foo=1&bar=baz#anchor';
$parts = parse_url($url);
Array
)
You can also selectively return just one component of the url. To return just the querystring:
$url = 'http://www.example.com/page?foo=1&bar=baz#anchor';
To further parse a query string into key value pairs use parse_str():
$params = [];
parse_str($queryString, $params);
After execution of the above, the $params array would be populated with the following:
Array
[foo] => 1
array
The http_build_query() will create a query string from an array or object. These strings can be
appended to a URL
to create a GET request, or used in a POST request with, for example, cURL.
$parameters = array(
);
$queryString = http_build_query($parameters);
parameter1=foo¶meter2=bar
$parameters = array(
),
);
$queryString = http_build_query($parameters);
parameter3%5Bsub1%5D=foo¶meter3%5Bsub2%5D=bar¶meter4=baz
parameter3[sub1]=foo¶meter3[sub2]=bar¶meter4=baz
You can use the header() function to instruct the browser to redirect to a different URL:
$url = 'https://example.org/foo/bar';
if (!headers_sent()) { // check headers - you can not send headers if they already sent
} else {
You can also redirect to a relative URL (this is not part of the official HTTP specification, but it does
work in all
browsers):
$url = 'foo/bar';
if (!headers_sent()) {
exit;
} else {
If headers have been sent, you can alternatively send a meta refresh HTML tag.
WARNING: The meta refresh tag relies on HTML being properly processed by the client, and some will
not do this.
In general, it only works in web browsers. Also, consider that if headers have been sent, you may have
a bug and
You may also print a link for users to click, for clients that ignore the meta refresh tag:
$url = 'https://example.org/foo/bar';
if (!headers_sent()) {
} else {
}
exit;
As you code PHP you will most likely get your self in a position where you need to break down an URL
into several
pieces. There's obviously more than one way of doing it depending on your needs. This article will
explain those
ways for you so you can find what works best for you.
parse_url(): This function parses a URL and returns an associative array containing any of the various
$url = parse_url('http://example.com/project/controller/action/param1/param2');
Array
$url = parse_url('http://example.com/project/controller/action/param1/param2');
Array
[0] =>
If you need the last part of the section you can use end() like this:
$last = end($url['sections']);
If the URL contains GET vars you can retrieve those as well
$url = parse_url('http://example.com?var1=value1&var2=value2');
Array
If you wish to break down the query vars you can use parse_str() like this:
$url = parse_url('http://example.com?var1=value1&var2=value2');
parse_str($url['query'], $parts);
Array
(
explode(): Returns an array of strings, each of which is a substring of string formed by splitting it on
$url = "http://example.com/project/controller/action/param1/param2";
Array
[1] =>
You can retrieve the last part of the URL by doing this:
$last = end($parts);
// Output: param2
You can also navigate inside the array by using sizeof() in combination with a math operator like this:
echo $parts[sizeof($parts)-2];
// Output: param1
basename(): Given a string containing the path to a file or directory, this function will return the
trailing
name component.
$url = "http://example.com/project/controller/action/param1/param2";
$parts = basename($url);
// Output: param2
If your URL has more stuff to it and what you need is the dir name containing the file you can use it
with dirname()
like this:
$url = "http://example.com/project/controller/action/param1/param2/index.php";
$parts = basename(dirname($url));
// Output: param2
serialize() returns a string containing a byte-stream representation of any value that can be stored in
PHP.
unserialize() can use this string to recreate the original variable values.
To serialize an object
serialize($object);
To Unserialize an object
unserialize($object)
Example
$array = array();
$array["a"] = "Foo";
$array["b"] = "Bar";
$array["c"] = "Baz";
$array["d"] = "Wom";
$serializedArray = serialize($array);
a:4:{s:1:"a";s:3:"Foo";s:1:"b";s:3:"Bar";s:1:"c";s:3:"Baz";s:1:"d";s:3:"Wom";}
Introduction
Classes that implement this interface no longer support __sleep() and __wakeup(). The method
serialize
is called whenever an instance needs to be serialized. This does not invoke __destruct() or has any
other side effect unless programmed inside the method. When the data is unserialized the class is
known and the appropriate unserialize() method is called as a constructor instead of calling
__construct(). If you need to execute the standard constructor you may do so in the method.
Basic usage
private $data;
return serialize($this->data);
}
public function unserialize($data) {
$this->data = unserialize($data);
return $this->data;
$ser = serialize($obj);
$newobj = unserialize($ser);
Parameter Details
value
The value to be serialized. serialize() handles all types, except the resource-type. You can even
serialize() arrays that contain references to itself. Circular references inside the array/object you are
serializing will also be stored. Any other reference will be lost. When serializing objects, PHP will
attempt to call the member function __sleep() prior to serialization. This is to allow the object to do
any
last minute clean-up, etc. prior to being serialized. Likewise, when the object is restored using
unserialize() the __wakeup() member function is called. Object's private members have the class name
prepended to the member name; protected members have a '*' prepended to the member name.
This is useful for storing or passing PHP values around without losing their type and structure.
To make the serialized string into a PHP value again, use unserialize().
Serializing a string
echo serialize($string);
// Output:
// s:11:"Hello world";
Serializing a double
$double = 1.5;
echo serialize($double);
// Output:
// d:1.5;
Serializing a float
Serializing an integer
$integer = 65;
echo serialize($integer);
// Output:
// i:65;
Serializing a boolean
$boolean = true;
echo serialize($boolean);
// Output:
// b:1;
$boolean = false;
echo serialize($boolean);
// Output:
// b:0;
Serializing null
$null = null;
echo serialize($null);
// Output:
// N;
Serializing an array
$array = array(
25,
'String',
'boolean'=> true,
null,
3.445
);
echo serialize($array);
// Output:
// a:7:{i:0;i:25;i:1;s:6:"String";s:5:"Array";a:2:{i:0;s:15:"Multi
Dimension";i:1;s:5:"Array";}s:7:"boolean";b:1;s:6:"Object";O:3:"abc":1:{s:1:"i";i:1;}i:2;N;i:3;d:3.44
49999999999998;}
Serializing an object
When serializing objects, PHP will attempt to call the member function __sleep() prior to serialization.
This is to
allow the object to do any last minute clean-up, etc. prior to being serialized. Likewise, when the
object is restored
class abc {
var $i = 1;
function foo() {
echo serialize($object);
// Output:
// O:3:"abc":1:{s:1:"i";i:1;}
Warning Do not pass untrusted user input to unserialize(). Unserialization can result in code being
loaded and executed due to object instantiation and autoloading, and a malicious user may be able to
exploit this. Use a safe, standard data interchange format such as JSON (via json_decode() and
Possible Attacks
PHP Object Injection is an application level vulnerability that could allow an attacker to perform
different kinds of
malicious attacks, such as Code Injection, SQL Injection, Path Traversal and Application Denial of
Service, depending
on the context. The vulnerability occurs when user-supplied input is not properly sanitized before
being passed to
the unserialize() PHP function. Since PHP allows object serialization, attackers could pass ad-hoc
serialized strings to
a vulnerable unserialize() call, resulting in an arbitrary PHP object(s) injection into the application
scope.
In order to successfully exploit a PHP Object Injection vulnerability two conditions must be met:
The application must have a class which implements a PHP magic method (such as __wakeup or
__destruct)
that can be used to carry out malicious attacks, or to start a "POP chain".
All of the classes used during the attack must be declared when the vulnerable unserialize() is being
The example below shows a PHP class with an exploitable __destruct method:
class Example1
public $cache_file;
function __construct()
function __destruct()
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) @unlink($file);
$user_data = unserialize($_GET['data']);
In this example an attacker might be able to delete an arbitrary file via a Path Traversal attack, for e.g.
requesting
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
The example below shows a PHP class with an exploitable __wakeup method:
class Example2
private $hook;
function __construct()
function __wakeup()
if (isset($this->hook)) eval($this->hook);
$user_data = unserialize($_COOKIE['data']);
In this example an attacker might be able to perform a Code Injection attack by sending an HTTP
request like this:
Host: testsite.com
Cookie:
data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs
%3A10%3A%22phpinfo%28%29%
3B%22%3B%7D
Connection: close
Where the cookie parameter "data" has been generated by the following script:
class Example2
}
print urlencode(serialize(new Example2));
A closure is the PHP equivalent of an anonymous function, eg. a function that does not have a name.
Even if that is
technically not correct, the behavior of a closure remains the same as a function's, with a few extra
features.
A closure is nothing but an object of the Closure class which is created by declaring a function without
a name. For
example:
<?php
$myClosure = function() {
};
Keep in mind that $myClosure is an instance of Closure so that you are aware of what you can truly do
with it (cf.
http://fr2.php.net/manual/en/class.closure.php )
The classic case you would need a Closure is when you have to give a callable to a function, for
instance usort.
Here is an example where an array is sorted by the number of siblings of each person:
<?php
$data = [
'nbrOfSiblings' => 2,
],
'nbrOfSiblings' => 1,
],
'nbrOfSiblings' => 3,
];
if ($e1['nbrOfSiblings'] == $e2['nbrOfSiblings']) {
return 0;
});
var_dump($data); // Will show Stan first, then John and finally Tom
It is possible, inside a closure, to use an external variable with the special keyword use. For instance:
<?php
$quantity = 1;
You can go further by creating "dynamic" closures. It is possible to create a function that returns a
specific
<?php
function createCalculator($quantity) {
};
$calculator1 = createCalculator(1);
$calculator2 = createCalculator(2);
As seen previously, a closure is nothing but an instance of the Closure class, and different methods can
be invoked
on them. One of them is bindTo, which, given a closure, will return a new one that is bound to a given
object. For
example:
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
{
public $property;
$this->property = $propertyValue;
$myBoundClosure = $myClosure->bindTo($myInstance);
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
public $property;
$this->property = $propertyValue;
Try to change the property visibility to either protected or private. You get a fatal error indicating that
you do not
have access to this property. Indeed, even if the closure has been bound to the object, the scope in
which the
closure is invoked is not the one needed to have that access. That is what the second argument of
bindTo is for.
The only way for a property to be accessed if it's private is that it is accessed from a scope that allows
it, ie. the
class's scope. In the just previous code example, the scope has not been specified, which means that
the closure
has been invoked in the same scope as the one used where the closure has been created. Let's change
that:
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
$this->property = $propertyValue;
As just said, if this second parameter is not used, the closure is invoked in the same context as the one
used where
the closure has been created. For example, a closure created inside a method's class which is invoked
in an object
<?php
class MyClass
private $property;
$this->property = $propertyValue;
return function() {
echo $this->property;
};
$displayer = $myInstance->getDisplayer();
<?php
class MyClass
private $property;
$this->property = $propertyValue;
$myClosure = function() {
echo $this->property;
};
As opposed to the bindTo method, there is no scope to worry about. The scope used for this call is the
same as the
In general, an observer is a class with a specific method being called when an action on the observed
object occurs.
In certain situations, closures can be enough to implement the observer design pattern.
Here is a detailed example of such an implementation. Let's first declare a class whose purpose is to
notify
<?php
protected $property;
$this->observers[] = $observer;
return $this;
unset($this->observers[$key]);
$observer->update($this);
return $this->property;
}
public function setProperty($property)
$this->property = $property;
$this->notify();
Then, let's declare the class that will represent the different observers.
<?php
protected $name;
protected $closure;
$this->name = $name;
$closure = $this->closure;
$closure($subject);
<?php
$o = new ObservedStuff;
echo $this->name, ' has been notified! New property value: ', $subject->getProperty(), "\n";
};
echo $this->name, ' has been notified! New property value: ', $subject->getProperty(), "\n";
};
$o->setProperty('Hello world!');
// Shows:
Note that this example works because the observers share the same nature (they are both "named
observers.")
Usually data sent in a POST request is structured key/value pairs with a MIME type of application/x-
www-formurlencoded. However many applications such as web services require raw data, often in
XML or JSON format, to be
sent instead. This data can be read using one of two methods.
$rawdata = file_get_contents("php://input");
$decoded = json_decode($rawdata);
Version < 5.6
$HTTP_RAW_POST_DATA is a global variable that contains the raw POST data. It is only available if the
$rawdata = $HTTP_RAW_POST_DATA;
$decoded = simplexml_load_string($rawdata);
This variable has been deprecated since PHP version 5.6, and was removed in PHP 7.0.
Note that neither of these methods are available when the content type is set to multipart/form-data,
which is
Data from a POST request is stored in the superglobal $_POST in the form of an associative array.
Note that accessing a non-existent array item generates a notice, so existence should always be
checked with the
Example:
Version ≥ 7.0
Data from a GET request is stored in the superglobal $_GET in the form of an associative array.
Note that accessing a non-existent array item generates a notice, so existence should always be
checked with the
isset() or empty() functions, or the null coalesce operator.
Version ≥ 7.0
The $_FILES["FILE_NAME"]['error'] (where "FILE_NAME" is the value of the name attribute of the file
input,
3. UPLOAD_ERR_PARTIAL - The uploaded file exceeds the MAX_FILE_SIZE directive that was specified
in the HTML
form.
7. UPLOAD_ERR_EXTENSION - A PHP extension stopped the file upload. (From PHP 5.2.0).
<?php
switch($fileError) {
case UPLOAD_ERR_INI_SIZE:
break;
case UPLOAD_ERR_PARTIAL:
break;
case UPLOAD_ERR_NO_FILE:
break;
case UPLOAD_ERR_NO_TMP_DIR:
break;
case UPLOAD_ERR_CANT_WRITE:
break;
default:
break;
Usually, an HTML form element submitted to PHP results in a single value. For example:
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<button type="submit">Submit</button>
</form>
Array
However, there may be cases where you want to pass an array of values. This can be done by adding a
PHP-like
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<button type="submit">Submit</button>
</form>
Array
You can also specify the array indices, as either numbers or strings:
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<button type="submit">Submit</button>
</form>
Array
This technique can be used to avoid post-processing loops over the $_POST array, making your code
leaner and
more concise.
PHP provides support for the HTTP PUT method used by some clients to store files on a server. PUT
requests are
much simpler than a file upload using POST requests and they look something like this:
Into your PHP code you would then do something like this:
<?php
fwrite($fp, $data);
fclose($fp);
fclose($putdata);
?>
Also here you can read interesting SO question/answers about receiving file via HTTP PUT.
Comparison Issues
PHP is a loosely typed language. This means that, by default, it doesn't require operands in an
expression to be of
the same (or compatible) types. For example, you can append a number to a string and expect it to
work.
PHP accomplishes this by automatically casting incompatible variable types into types that allow the
requested
operation to take place. In the case above, it will cast the integer literal 1 into a string, meaning that it
can be
concatenated onto the preceding string literal. This is referred to as type juggling. This is a very
powerful feature of
PHP, but it is also a feature that can lead you to a lot of hair-pulling if you are not aware of it, and can
even lead to
security problems.
if (1 == $variable) {
// do something
The intent appears to be that the programmer is checking that a variable has a value of 1. But what
happens if
$variable has a value of "1 and a half" instead? The answer might surprise you.
var_dump (1 == $variable);
bool(true)
Why has this happened? It's because PHP realised that the string "1 and a half" isn't an integer, but it
needs to be in
order to compare it to integer 1. Instead of failing, PHP initiates type juggling and, attempts to convert
the variable
into an integer. It does this by taking all the characters at the start of the string that can be cast to
integer and
casting them. It stops as soon as it encounters a character that can't be treated as a number. Therefore
"1 and a
Granted, this is a very contrived example, but it serves to demonstrate the issue. The next few
examples will cover
some cases where I've run into errors caused by type juggling that happened in real software.
When reading from a file, we want to be able to know when we've reached the end of that file.
Knowing that
fgets() returns false at the end of the file, we might use this as the condition for a loop. However, if the
data
returned from the last read happens to be something that evaluates as boolean false, it can cause our
file read
fclose ($handle);
If the file being read contains a blank line, the while loop will be terminated at that point, because the
empty string
evaluates as boolean false.
Instead, we can check for the boolean false value explicitly, using strict equality operators:
Note this is a contrived example; in real life we would use the following loop:
while (!feof($handle)) {
$data = fgets($handle);
$filedata = file("/path/to/my/file");
Switch statements use non-strict comparison to determine matches. This can lead to some nasty
surprises. For
switch ($name) {
$mode = 'output_1';
break;
$mode = 'output_2';
break;
default:
$mode = 'unknown';
break;
This is a very simple statement, and works as expected when $name is a string, but can cause
problems otherwise.
For example, if $name is integer 0, then type-juggling will happen during the comparison. However,
it's the literal
value in the case statement that gets juggled, not the condition in the switch statement. The string
"input 1" is
converted to integer 0 which matches the input value of integer 0. The upshot of this is if you provide
a value of
Explicit casting
switch ((string)$name) {
...
switch (strval($name)) {
...
Both of these methods ensure the value is of the same type as the value in the case statements.
Avoid switch
Using an if statement will provide us with control over how the comparison is done, allowing us to use
strict
comparison operators:
$mode = "output_1";
$mode = "output_2";
} else {
$mode = "unknown";
Since PHP 7.0, some of the harmful effects of type juggling can be mitigated with strict typing. By
including this
declare statement as the first line of the file, PHP will enforce parameter type declarations and return
type
declare(strict_types=1);
For example, this code, using parameter type definitions, will throw a catchable exception of type
TypeError when
run:
<?php
declare(strict_types=1);
return $a + $b;
Likewise, this code uses a return type declaration; it will also throw an exception if it tries to return
anything other
GoalKicker.com – PHP Notes for Professionals 297
than an integer:
<?php
declare(strict_types=1);
return $a;
returner("this is a string");
Make sure the socket is successfully created. The onSocketFailure function comes from Handling
socket errors
The socket_write function sends bytes through a socket. In PHP, a byte array is represented by a string,
which is
normally encoding-insensitive.
The following snippet receives some data from the server using the socket_read function.
Passing PHP_NORMAL_READ as the third parameter reads until a \r/\n byte, and this byte is included
in the return
value.
Passing PHP_BINARY_READ, on the contrary, reads the required amount of data from the stream.
If socket_set_nonblock was called in prior, and PHP_BINARY_READ is used, socket_read will return
false
immediately. Otherwise, the method blocks until enough data (to reach the length in the second
parameter, or to
while(true) {
socket_read($socket, 1, PHP_BINARY_READ);
$message = parseLine($line);
Closing the socket frees the socket and its associated resources.
Socket creation
Create a socket that uses the TCP. It is the same as creating a client socket.
Socket binding
Bind connections from a given network (parameter 2) for a specific port (parameter 3) to the socket.
The second parameter is usually "0.0.0.0", which accepts connection from all networks. It can also
One common cause of errors from socket_bind is that the address specified is already bound to
another process.
Other processes are usually killed (usually manually to prevent accidentally killing critical processes)
so that the
Make the socket listen to incoming connections using socket_listen. The second parameter is the
maximum
socket_listen($socket, 5);
Handling connection
A TCP server is actually a server that handles child connections. socket_accept creates a new child
connection.
$conn = socket_accept($socket);
Data transferring for a connection from socket_accept is the same as that for a TCP client socket.
When this connection should be closed, call socket_close($conn); directly. This will not affect the
original TCP
server socket.
Closing the server
On the other hand, socket_close($socket); should be called when the server is no longer used. This will
free the
A UDP (user datagram protocol) server, unlike TCP, is not stream-based. It is packet-based, i.e. a client
sends data in
units called "packets" to the server, and the client identifies clients by their address. There is no builtin
function that
relates different packets sent from the same client (unlike TCP, where data from the same client are
handled by a
specific resource created by socket_accept). It can be thought as a new TCP connection is accepted and
closed
$socket);
Sending a packet
Receiving a packet
$clients = [];
while (true){
$address = "$ip:$port";
$clients[$address]->handlePacket($buffer);
socket_close can be used on the UDP server socket resource. This will free the UDP address, allowing
other
socket_last_error can be used to get the error ID of the last error from the sockets extension.
if(is_resource($socket)) {
die($message);
The PDO (PHP Data Objects) extension allows developers to connect to numerous different types of
databases and
SQL injection is a kind of attack that allows a malicious user to modify the SQL query, adding
unwanted commands
$sql = 'SELECT name, email, user_level FROM users WHERE userID = ' . $_GET['user'];
$conn->query($sql);
This allows any user of this script to modify our database basically at will. For example consider the
following query
string:
page.php?user=0;%20TRUNCATE%20TABLE%20users;
SELECT name, email, user_level FROM users WHERE userID = 0; TRUNCATE TABLE users;
While this is an extreme example (most SQL injection attacks do not aim to delete data, nor do most
PHP query
execution functions support multi-query), this is an example of how a SQL injection attack can be
made possible by
the careless assembly of the query. Unfortunately, attacks like this are very common, and are highly
effective due to
To prevent SQL injection from occurring, prepared statements are the recommended solution. Instead
of
concatenating user data directly to the query, a placeholder is used instead. The data is then sent
separately, which
means there is no chance of the SQL engine confusing user data for a set of instructions.
While the topic here is PDO, please note that the PHP MySQLi extension also supports prepared
statements
PDO supports two kinds of placeholders (placeholders cannot be used for column or table names, only
values):
1. Named placeholders. A colon(:), followed by a distinct name (eg. :user)
$sql = 'SELECT name, email, user_level FROM users WHERE userID = :user';
$prep = $conn->prepare($sql);
$result = $prep->fetchAll();
$sql = 'SELECT name, user_level FROM users WHERE userID = ? AND user_level = ?';
$prep = $conn->prepare($sql);
$result = $prep->fetchAll();
If ever you need to dynamically change table or column names, know that this is at your own security
risks and a
bad practice. Though, it can be done by string concatenation. One way to improve security of such
queries is to set
a table of allowed values and compare the value you want to concatenate to this table.
Be aware that it is important to set connection charset through DSN only, otherwise your application
could be
prone to an obscure vulnerability if some odd encoding is used. For PDO versions prior to 5.3.6 setting
charset
through DSN is not available and thus the only option is to set PDO::ATTR_EMULATE_PREPARES
attribute to false on
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
This causes PDO to use the underlying DBMS’s native prepared statements instead of just emulating it.
However, be aware that PDO will silently fallback to emulating statements that MySQL cannot prepare
natively:
Since PHP 5.0, PDO has been available as a database access layer. It is database agnostic, and so the
following
connection example code should work for any of its supported databases simply by changing the DSN.
$dsn = "mysql:host=localhost;dbname=testdb;charset=utf8";
//Using MySQL (connection via network, optionally you can specify the port too):
//$dsn = "mysql:host=127.0.0.1;port=3306;dbname=testdb;charset=utf8";
//Or Postgres
//$dsn = "pgsql:host=localhost;port=5432;dbname=testdb;";
//$dsn = "sqlite:/path/to/database"
$username = "user";
$password = "pass";
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$statement = $db->prepare($query);
// Create some parameters to fill the placeholders, and execute the statement
$parameters = [ "221B" ];
$statement->execute($parameters);
do_stuff($row);
The prepare function creates a PDOStatement object from the query string. The execution of the
query and retrieval
of the results are performed on this returned object. In case of a failure, the function either returns
false or throws
Database transactions ensure that a set of data changes will only be made permanent if every
statement is
successful. Any query or code failure during a transaction can be caught and you then have the option
to roll back
PDO provides simple methods for beginning, committing, and rollbacking back transactions.
$dsn,
$username,
$password,
);
try {
$pdo->beginTransaction();
$statement->execute(["name"=>'Bob']);
$statement->execute(["name"=>'Joe']);
$pdo->commit();
if ($pdo->inTransaction()) {
$pdo->rollback();
// If we got here our two data updates are not in the database
throw $e;
During a transaction any data changes made are only visible to the active connection. SELECT
statements will return
the altered changes even if they are not yet committed to the database.
Note: See database vendor documentation for details about transaction support. Some systems do not
support
In the following section is demonstrated a practical real world example where the use of transactions
ensures the
consistency of database.
Imagine the following scenario, let's say you are building a shopping cart for an e-commerce website
and you
decided to keep the orders in two database tables. One named orders with the fields order_id, name,
address,
telephone and created_at. And a second one named orders_products with the fields order_id,
product_id and
quantity. The first table contains the metadata of the order while the second one the actual products
that have
been ordered.
To insert a new order into the database you need to do two things. First you need to INSERT a new
record inside the
orders table that will contain the metadata of the order (name, address, etc). And then you need to
INSERT one
record into the orders_products table, for each one of the products that are included in the order.
$preparedStatement = $db->prepare(
);
$preparedStatement->execute([
]);
$orderId = $db->lastInsertId();
VALUES';
$count = 0;
$count . ')';
++$count;
$preparedStatement = $db->prepare($insertProductsQuery);
$preparedStatement->execute($insertProductsParams);
This will work great for inserting a new order into the database, until something unexpected happens
and for some
reason the second INSERT query fails. If that happens you will end up with a new order inside the
orders table,
which will have no products associated to it. Fortunately, the fix is very simple, all you have to do is to
make the
To start a transaction using PDO all you have to do is to call the beginTransaction method before you
execute any
queries to your database. Then you make any changes you want to your data by executing INSERT
and / or UPDATE
queries. And finally you call the commit method of the PDO object to make the changes permanent.
Until you call the
commit method every change you have done to your data up to this point is not yet permanent, and
can be easily
On the following example is demonstrated the use of transactions for inserting a new order into the
database,
while ensuring the same time the consistency of the data. If one of the two queries fails all the
changes will be
reverted.
// In this example we are using MySQL but this applies to any database that has support for
transactions
$password);
// Make sure that PDO will throw an exception in case of error to make error handling easier
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
// From this point and until the transaction is being committed every change to the database can
be reverted
$db->beginTransaction();
$preparedStatement = $db->prepare(
);
$preparedStatement->execute([
'name' => $name,
]);
$orderId = $db->lastInsertId();
VALUES';
$count = 0;
$count . ')';
++$count;
$preparedStatement->execute($insertProductsParams);
$db->commit();
catch ( PDOException $e ) {
// Failed to insert the order into the database so we rollback any changes
$db->rollback();
throw $e;
There are two ways to connect to a MySQL/MariaDB server, depending on your infrastructure.
$dsn = 'mysql:dbname=demo;host=server;port=3306;charset=utf8';
$connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
Since PDO was designed to be compatible with older MySQL server versions (which did not have
support for
prepared statements), you have to explicitly disable the emulation. Otherwise, you will lose the added
injection
It is strongly recommended setting it to "exception mode", because that gains you additional
functionality, when
writing persistence abstractions (for example: having an exception, when violating UNIQUE
constraint).
Socket connection
$dsn = 'mysql:unix_socket=/tmp/mysql.sock;dbname=demo;charset=utf8';
$connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
On unix-like systems, if host name is 'localhost', then the connection to the server is made through a
domain
socket.
We start off with $db, an instance of the PDO class. After executing a query we often want to
determine the number
of rows that have been affected by it. The rowCount() method of the PDOStatement will work nicely:
NOTE: This method should only be used to determine the number of rows affected by INSERT, DELETE,
and UPDATE
statements. Although this method may work for SELECT statements as well, it is not consistent across
all databases.
database table. You can achieve this with the lastInsertId() method.
$host = 'localhost';
$database = 'foo';
$user = 'root'
$password = '';
$dsn = "mysql:host=$host;dbname=$database;charset=utf8";
$query_success = $pdo->query($query);
In postgresql and oracle, there is the RETURNING Keyword, which returns the specified columns of the
currently
$host = 'localhost';
$database = 'foo';
$user = 'root'
$password = '';
$dsn = "pgsql:host=$host;dbname=$database;charset=utf8";
RETURNING id";
$statement = $pdo->query($query);
$id = $statement->fetchColumn(); // return the value of the id column of the new row in foo_user
The mysqli interface is an improvement (it means "MySQL Improvement extension") of the mysql
interface, which
was deprecated in version 5.5 and is removed in version 7.0. The mysqli extension, or as it is
sometimes known, the
MySQL improved extension, was developed to take advantage of new features found in MySQL
systems versions
4.1.3 and newer. The mysqli extension is included with PHP versions 5 and later.
When we are finished querying the database, it is recommended to close the connection to free up
resources.
$conn->close();
Procedural style
mysqli_close($conn);
Note: The connection to the server will be closed as soon as the execution of the script ends, unless
it's closed
Use Case: If our script has a fair amount of processing to perform after fetching the result and has
retrieved the full
result set, we definitely should close the connection. If we were not to, there's a chance the MySQL
server will reach
its connection limit when the web server is under heavy use.
Connect to Server
Connect to Database
Procedural style
Connect to Server
$conn = mysqli_connect("localhost","my_user","my_password");
Connect to Database
$conn = mysqli_connect("localhost","my_user","my_password","my_db");
if ($conn->connect_errno > 0) {
trigger_error($db->connect_error);
Procedural style
if (!$conn) {
trigger_error(mysqli_connect_error());
PHP makes it easy to get data from your results and loop over it using a while statement. When it fails
to get the
next row, it returns false, and your loop ends. These examples work with
mysqli_fetch_array - Associative AND Numeric array (can use arguments to get one or the other)
while($row = $result->fetch_assoc()) {
var_dump($row);
Procedural style
while($row = mysqli_fetch_assoc($result)) {
var_dump($row);
Please read Preventing SQL injection with Parametrized Queries for a complete discussion of why
prepared
statements help you secure your SQL statements from SQL Injection attacks
The $conn variable here is a MySQLi object. See MySQLi connect example for more details.
For both examples, we assume that $sql is
FROM table
WHERE column_2 = ?
The ? represents the values we will provide later. Please note that we do not need quotes for the
placeholders,
regardless of the type. We can also only provide placeholders in the data portions of the query,
meaning SET,
VALUES and WHERE. You cannot use placeholders in the SELECT or FROM portions.
if ($stmt = $conn->prepare($sql)) {
$stmt->execute();
$stmt->bind_result($column_1);
$stmt->fetch();
//Now use variable $column_1 one as if it were any other PHP variable
$stmt->close();
Procedural style
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
}
i integer
d double
s string
b blob
Your list of parameters needs to be in the order provided in your query. In this example si means the
first
parameter (column_2 = ?) is string and the second parameter (column_3 > ?) is integer.
For retrieving data, see How to get data from a prepared statement
Escaping strings is an older (and less secure) method of securing data for insertion into a query. It
works by using
MySQL's function mysql_real_escape_string() to process and sanitize the data (in other words, PHP is
not doing the
$escaped = $conn->real_escape_string($_GET['var']);
// OR
At this point, you have a string that MySQL considers to be safe for use in a direct query
$result = $conn->query($sql);
So why is this not as secure as prepared statements? There are ways to trick MySQL to produce a
string it considers
GoalKicker.com – PHP Notes for Professionals 311
1 OR 1=1 does not represent data that MySQL will escape, yet this still represents SQL injection. There
are other
examples as well that represent places where it returns unsafe data. The problem is that MySQL's
escaping function
is designed to make data comply with SQL syntax. It's NOT designed to make sure that MySQL can't
confuse
So your query has failed (see MySQLi connect for how we made $conn)
How do we find out what happened? $result is false so that's no help. Thankfully the connect $conn
can tell us
trigger_error($conn->error);
or procedural
trigger_error(mysqli_error($conn));
The query function takes a valid SQL string and executes it directly against the database connection
$conn
CAUTION
A common problem here is that people will simply execute the query and expect it to work (i.e. return
a
mysqli_stmt object). Since this function takes only a string, you're building the query first yourself. If
there are any
mistakes in the SQL at all, the MySQL compiler will fail, at which point this function will return false.
$row = $result->fetch_assoc();
The above code will generate a E_FATAL error because $result is false, and not an object.
The procedural error is similar, but not fatal, because we're just violating the expectations of the
function.
Prepared statements
See Prepared statements in MySQLi for how to prepare and execute a query.
Binding of results
Object-oriented style
$stmt->bind_result($forename);
Procedural style
mysqli_stmt_bind_result($stmt, $forename);
The problem with using bind_result is that it requires the statement to specify the columns that will
be used. This
means that for the above to work the query must have looked like this SELECT forename FROM users.
To include
more columns simply add them as parameters to the bind_result function (and ensure that you add
them to the
SQL query).
In both cases, we're assigning the forename column to the $forename variable. These functions take
as many
arguments as columns you want to assign. The assignment is only done once, since the function binds
by reference.
Object-oriented style
while ($stmt->fetch())
Procedural style
while (mysqli_stmt_fetch($stmt))
The drawback to this is that you have to assign a lot of variables at once. This makes keeping track of
large queries
difficult. If you have MySQL Native Driver (mysqlnd) installed, all you need to do is use get_result.
Object-oriented style
$result = $stmt->get_result();
Procedural style
$result = mysqli_stmt_get_result($stmt);
This is much easier to work with because now we're getting a mysqli_result object. This is the same
object that
mysqli_query returns. This means you can use a regular result loop to get your data.
If that is the case then @Sophivorus has you covered with this amazing answer.
This function can perform the task of get_result without it being installed on the server. It simply loops
through
$result = array();
$statement->store_result();
$metadata = $statement->result_metadata();
$params = array();
$params[] = &$result[$i][$field->name];
$statement->fetch();
return $result;
We can then use the function to get results like this, just as if we were using mysqli_fetch_assoc()
<?php
$query = $mysqli->prepare("SELECT * FROM users WHERE forename LIKE ?");
$condition = "J%";
$query->bind_param("s", $condition);
$query->execute();
$result = get_result($query);
It will have the same output as if you were using the mysqlnd driver, except it does not have to be
installed. This is
very useful if you are unable to install said driver on your system. Just implement this solution.
Retrieve the last ID generated by an INSERT query on a table with an AUTO_INCREMENT column.
Object-oriented Style
$id = $conn->insert_id;
Procedural Style
$id = mysqli_insert_id($conn);
Returns zero if there was no previous query on the connection or if the query did not update an
AUTO_INCREMENT value.
Normally an UPDATE statement does not return an insert id, since an AUTO_INCREMENT id is only
returned when a
new row has been saved (or inserted). One way of making updates to the new id is to use INSERT ...
ON
PRIMARY KEY(id),
UNIQUE(name)
) ENGINE=InnoDB;
VALUES
('Leslie', 123),
('Sally', 456);
+----+--------+------+
| id | name | misc |
+----+--------+------+
| 1 | Leslie | 123 |
| 2 | Sally | 456 |
+----+--------+------+
The case of IODKU performing an "update" and LAST_INSERT_ID() retrieving the relevant id:
VALUES
id = LAST_INSERT_ID(id),
misc = VALUES(misc)";
$conn->query($sql);
The case where IODKU performs an "insert" and LAST_INSERT_ID() retrieves the new id:
VALUES
id = LAST_INSERT_ID(id),
misc = VALUES(misc);
$conn->query($sql);
+----+--------+------+
| id | name | misc |
+----+--------+------+
| 1 | Leslie | 123 |
+----+--------+------+
really fast. You can also get a runnable PHP file of of this tutorial.
Creating/opening a database
Let's create a new database first. Create it only if the file doesn't exist and open it for reading/writing.
The extension
Creating a table
"user_id" INTEGER,
"url" VARCHAR,
"time" DATETIME
)');
It's advisable to wrap related queries in a transaction (with keywords BEGIN and COMMIT), even if you
don't care
about atomicity. If you don't do this, SQLite automatically wraps every single query in a transaction,
which slows
down everything immensely. If you're new to SQLite, you may be surprised why the INSERTs are so
slow .
$db->exec('BEGIN');
Insert potentially unsafe data with a prepared statement. You can do this with named parameters:
$statement->bindValue(':uid', 1337);
$statement->bindValue(':url', '/test');
Fetching data
Let's fetch today's visits of user #42. We'll use a prepared statement again, but with numbered
parameters this time,
$statement = $db->prepare('SELECT * FROM "visits" WHERE "user_id" = ? AND "time" >= ?');
$statement->bindValue(1, 42);
$statement->bindValue(2, '2017-01-14');
$result = $statement->execute();
print_r($result->fetchArray(SQLITE3_ASSOC));
echo "\n";
print_r($result->fetchArray(SQLITE3_NUM));
echo "\n";
Note: If there are no more rows, fetchArray() returns false. You can take advantage of this in a while
loop.
Free the memory - this in not done automatically, while your script is running
$result->finalize();
Shorthands
Here's a useful shorthand for fetching a single row as an associative array. The second parameter
means we want
Watch out, this shorthand doesn't support parameter binding, but you can escape the strings instead.
Always put
the values in SINGLE quotes! Double quotes are used for table and column names (similar to backticks
in MySQL).
SQLite3::escapeString('/test') .
print_r($lastVisit);
echo "\n";
echo "\n";
Cleaning up
Finally, close the database. This is done automatically when the script finishes, though.
$db->close();
<?php
//Iterate through all of the results, var_dumping them onto the page
var_dump($row);
?>
In addition to using LIMIT SQL statements you can also use the SQLite3 function querySingle to
retrieve a single
<?php
//Without the optional second parameter set to true, this query would return just
//the first column of the first row of results and be of the same type as columnName
//With the optional entire_row parameter, this query would return an array of the
?>
In the next example, you will learn how to query the connection object.
This extension close the connection automatically, it's not necessary to close manually.
var_dump($doc);
Example for searching just one user with a specific id, you should do:
$cursorArray = $cursor->toArray();
if(isset($cursorArray[0])) {
var_dump($cursorArray[0]);
$document = [
'name' => 'John',
];
$_id1 = $bulk->insert($document);
$bulk->update(
$filter,
$document,
);
$bulk->delete($filter);
Requirements
MongoDB server running on port usually 27017. (type mongod on command prompt to run mongodb
server)
Php installed as either cgi or fpm with MongoDB extension installed(MongoDB extension is not
bundled with
default php)
if not sure check Php installation by running php -v on command prompt will return something like
this
PHP 7.0.6 (cli) (built: Apr 28 2016 14:12:14) ( ZTS ) Copyright (c) 1997-2016 The PHP Group Zend
Check MongoDB installation by running mongo --version will return MongoDB shell version: 3.2.6
Check for Composer installation by running php composer.phar --version will return Composer version
1.2-dev
<?php
//This path should point to Composer's autoloader from where your MongoDB library will be loaded
require 'vendor/autoload.php';
// when using custom username password
try {
print_r($mongo->listDatabases());
echo $e->getMessage();
try {
print_r($mongo->listDatabases());
echo $e->getMessage();
The above code will connect using MongoDB composer library(mongodb/mongodb) included as
vendor/autoload.php to
connect to the MongoDB server running on port: 27017. If everything is ok it will connect and list an
array, if exception
<?php
//NOTE: if database(here demo) and collection(here beers) are not found in MongoDB both will be
?>
In the example we are using the $mongo instance previously used in the Connecting to MongoDB from
php part.
MongoDB uses JSON type data format, so in php we will use array to insert data into MongoDB, this
conversion from array
to Json and vice versa will be done by mongo library. Every document in MongoDB has a unique id
named as _id,during
READ(Find) in MongoDB
<?php
//use find() method to query for records, where parameter will be array containing key value pair we
need to find.
?>
Drop in MongoDB
<?php
$result = $collection->drop( [ 'name' => 'Hinterland'] );
print_r($result->ok);
?>
There are many methods that can be performed on $collection see Official documentation from
MongoDB
Assuming a default server running on localhost with the default port, the command to connect to that
Redis server
would be:
$redis->connect('127.0.0.1', 6379);
The Redis PHP module gives access to the same commands as the Redis CLI client so it is quite
straightforward to
use.
$redis->set('mykey-1', 123);
$redis->set('mykey-2', 'abcd');
var_dump($redis->get('mykey-1'));
var_dump($redis->keys('mykey-*'));
Parameter Details
string $additional_parameters Optional: arguments to pass to the configured mail send application in
the
command line
full example
2. A subject
3. A message body
Sending mail in PHP can be as simple as calling the built-in function mail(). mail() takes up to five
parameters but
the first three are all that is required to send an email (although the four parameters is commonly
used as will be
3. The body of the email (string) (e.g. the content of the email)
The simple example above works well in limited circumstances such as hardcoding an email alert for
an internal
system. However, it is common to place the data passed as the parameters for mail() in variables to
make the
code cleaner and easier to manage (for example, dynamically building an email from a form
submission).
Additionally, mail() accepts a fourth parameter which allows you to have additional mail headers sent
with your
the From name and email address the user will see
additional non-standards headers like X-Mailer which can tell the recipient this email was sent via PHP
$message = 'This is the email message body'; // Could also be $message = $_POST['message'];
$headers = implode("\r\n", [
'Reply-To: webmaster@example.com',
The optional fifth parameter can be used to pass additional flags as command line options to the
program
configured to be used when sending mail, as defined by the sendmail_path configuration setting. For
example, this
can be used to set the envelope sender address when using sendmail/postfix with the -f sendmail
option.
$fifth = '-fno-reply@example.com';
Although using mail() can be pretty reliable, it is by no means guaranteed that an email will be sent
when mail() is
called. To see if there is a potential error when sending your email, you should capture the return
value from
mail(). TRUE will be returned if the mail was successfully accepted for delivery. Otherwise, you will
receive FALSE.
NOTE: Although mail() may return TRUE, it does not mean the email was sent or that the email will be
received by
the recipient. It only indicates the mail was successfully handed over to your system's mail system
successfully.
If you wish to send an HTML email, there isn't a lot more work you need to do. You need to:
$to = 'recipient@example.com';
$headers = implode("\r\n", [
'MIME-Version: 1.0',
]);
<?php
error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");
// Special mail settings that can make mail less likely to be considered spam
ini_set("mail.log", "/tmp/mail.log");
ini_set("mail.add_x_header", TRUE);
$to = 'recipient@example.com';
$headers = implode("\r\n", [
'From: webmaster@example.com',
'Reply-To: webmaster@example.com',
]);
if ($result) {
exit;
else {
See Also
Official documentation
mail()
How do you make sure email you send programmatically is not automatically marked as spam?
Alternative Mailers
PHPMailer
SwiftMailer
PEAR::Mail
Email Servers
Related Topics
Post/Redirect/Get
<?php
$to = 'recipent@example.com';
italic.</i></p></body></html>';
$headers = implode("\r\n", [
"Reply-To: webmaster@example.com",
"MIME-Version: 1.0",
]);
This is not much different then sending a plain text email. Thet key differences being the content body
is structured
like an HTML document and there are two additional headers that must be included so the email
client knows to
<?php
$to = 'recipient@example.com';
$attachment = '/path/to/your/file.pdf';
$content = file_get_contents($attachment);
$content = chunk_split(base64_encode($content));
// headers
$headers = implode("\r\n", [
'From: webmaster@example.com',
'Reply-To: webmaster@example.com',
'MIME-Version: 1.0',
"Content-Transfer-Encoding: 7bit",
]);
$message = implode("\r\n", [
"Content-Transfer-Encoding: 8bit",
$message,
"Content-Transfer-Encoding: base64",
"Content-Disposition: attachment",
$content,
]);
if ($result) {
exit;
else {
Content-Transfer-Encodings
The available encodings are 7bit, 8bit, binary, quoted-printable, base64, ietf-token, and x-token. Of
these encodings,
when a header has a multipart Content-Type, the Content-Transfer-Encoding must not be any other
value other
Our example chooses the 7bit encoding, which represents US-ASCII characters, for the multipart
header because,
as noted in RFC 2045 section 6, some protocols support only this encoding. Data within the boundaries
can then be
encoded on a part-by-part basis (RFC 2046, section 5.1). This example does exactly this. The first part,
which
contains the text/plain message, is defined to be 8bit since it may be necessary to support additional
characters. In
this case, the Latin1 (iso-8859-1) character set is being used. The second part is the attachment and so
it is defined
as a base64-encoded application/octet-stream. Since base64 transforms arbitrary data into the 7bit
range, it can be
<?php
$mail->From = "from@example.com";
if($mail->send()) {
exit;
else {
}
Adding addtional recipients, CC recipients, BCC recipients
<?php
$mail->From = "from@example.com";
$mail->addAddress("recepient2@example.com");
$mail->addCC("cc@example.com");
$mail->addBCC("bcc@example.com");
if($mail->send()) {
exit;
else {
<?php
$mail->addAddress("recepient2@example.com");
$mail->addCC("cc@example.com");
$mail->addBCC("bcc@example.com");
$mail->isHTML(true);
italic.</i></p></body></html>";
if($mail->send()) {
exit;
else {
PHPMailer
<?php
$mail->From = "from@example.com";
$mail->Body = "This is a sample basic text email with an attachment using PHPMailer.";
$attachment = '/path/to/your/file.pdf';
$mail->AddAttachment($attachment , 'RenamedFile.pdf');
// Add Second Attachment, run-time created. ie: CSV to be open with Excel
$csvHeader = "header1,header2,header3";
$csvData = "row1col1,row1col2,row1col3\nrow2col1,row2col2,row2col3";
'application/vnd.ms-excel');
if($mail->send()) {
exit;
else {
}
Section 64.7: Sending Plain Text Email Using Sendgrid
<?php
$email->addTo("recipient@example.com")
->setFrom("sender@example.com")
->setSubject("Subject Text")
$sendgrid->send($email);
<?php
$email->addTo("recipient@example.com")
->setFrom("sender@example.com")
->setSubject("Subject Text")
italic.</i></p></body></html>");
$personalization->addTo($email);
$personalization->addBcc($email);
$email->addPersonalization($personalization);
$sendgrid->send($email);
Sendgrid
<?php
$email->addTo("recipient@example.com")
->setFrom("sender@example.com")
->setSubject("Subject Text")
$attachment = '/path/to/your/file.pdf';
$content = file_get_contents($attachment);
$content = chunk_split(base64_encode($content));
$attachment->setContent($content);
$attachment->setType("application/pdf");
$attachment->setFilename("RenamedFile.pdf");
$attachment->setDisposition("attachment");
$email->addAttachment($attachment);
$sendgrid->send($email);
When a query goes wrong, it is important to fetch the error message(s) returned by the driver to
identify the cause
sqlsrv_errors([int $errorsOrWarnings]);
Key Description
sqlsrv_fetch_array()
while($row = sqlsrv_fetch_array($stmt)) {
echo $row[0];
$var = $row["name"];
//...
sqlsrv_fetch_array() has an optional second parameter to fetch back different types of array:
sqlsrv_fetch_object()
while($obj = sqlsrv_fetch_object($stmt)) {
echo $obj->field; // Object property names are the names of the fields from the query
//...
sqlsrv_fetch()
$dbServer = "localhost,1234"; //Name of the server/instance, including optional port number (default
is 1433)
$connectionInfo = array(
);
//Create Connection
Note: the use of square brackets [] is to escape the word table as it is a reserved word. These work in
the same way as
backticks ` do in MySQL.
array($name, SQLSRV_PARAM_IN),
array($age, SQLSRV_PARAM_IN),
);
If you plan on using the same query statement more than once, with different parameters, the same
can be
$cart = array(
"apple" => 3,
"banana" => 1,
"chocolate" => 2
);
die(print_r(sqlsrv_errors(), true));
}
Program options can be handled with the getopt() function. It operates with a similar syntax to the
POSIX getopt
#!/usr/bin/php
$shortopts = "hf:v::d";
if (isset($opts["h"]) || isset($opts["help"])) {
exit;
if (isset($opts["version"])) {
exit;
}
// options with values can be called like "-f foo", "-ffoo", or "-f=foo"
$file = "";
if (isset($opts["f"])) {
$file = $opts["f"];
if (empty($file)) {
exit(1);
$verbosity = 0;
if (isset($opts["v"])) {
$debug = 0;
if (isset($opts["d"])) {
./test.php --help
GoalKicker.com – PHP Notes for Professionals 337
./test.php --version
./test.php -v -d -ffoo
./test.php -f foo -v 5 -d
Note the last method will not work because -v 5 is not valid.
Arguments are passed to the program in a manner similar to most C-style languages. $argc is an
integer containing
the number of arguments including the program name, and $argv is an array containing arguments to
the
#!/usr/bin/php
unset($argv[0]);
Calling the above application with php example.php foo bar (where example.php contains the above
code) will
Argument 1 is foo
Argument 2 is bar
Note that $argc and $argv are global variables, not superglobal variables. They must be imported into
the local
This example shows the how arguments are grouped when escapes such as "" or \ are used.
Example script
var_dump($argc, $argv);
Command line
$ php argc.argv.php --this-is-an-option three\ words\ together or "in one quote" but\ multiple\
int(6)
array(6) {
[0]=>
string(13) "argc.argv.php"
[1]=>
string(19) "--this-is-an-option"
[2]=>
[3]=>
string(2) "or"
[4]=>
[5]=>
array(1) {
[0]=>
string(1) "-"
array(1) {
[0]=>
string(1) "-"
When run from the CLI, the constants STDIN, STDOUT, and STDERR are predefined. These constants
are file
handles, and can be considered equivalent to the results of running the following commands:
The constants can be used anywhere a standard file handle would be:
#!/usr/bin/php
$line = strtolower(trim($line));
switch ($line) {
case "bad":
break;
case "quit":
exit;
default:
break;
The builtin stream addresses referenced earlier (php://stdin, php://stdout, and php://stderr) can be
used in
fclose($stdout);
As an alternative, you can also use readline() for input, and you can also use echo or print or any other
string
The exit construct can be used to pass a return code to the executing environment.
#!/usr/bin/php
if ($argv[1] === "bad") {
exit(1);
} else {
exit(0);
By default an exit code of 0 will be returned if none is provided, i.e. exit is the same as exit(0). As exit
is not a
Return codes must be in the range of 0 to 254 (255 is reserved by PHP and should not be used). By
convention,
exiting with a return code of 0 tells the calling program that the PHP script ran successfully. Use a non-
zero return
code to tell the calling program that a specific error condition occurred.
The function php_sapi_name() and the constant PHP_SAPI both return the type of interface (Server
API) that is
being used by PHP. They can be used to restrict the execution of a script to the command line, by
checking whether
} else {
The drupal_is_cli() function is an example of a function that detects whether a script has been
executed from
function drupal_is_cli() {
return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' ||
When running from the CLI, PHP exhibits some different behaviours than when run from a web server.
These
differences should be kept in mind, especially in the case where the same script might be run from
both
environments.
No directory change When running a script from a web server, the current working directory is always
that
of the script itself. The code require("./stuff.inc"); assumes the file is in the same directory as the
script.
On the command line, the current working directory is the directory you're in when you call the script.
Scripts
that are going to be called from the command line should always use absolute paths. (Note the magic
constants __DIR__ and __FILE__ continue to work as expected, and return the location of the script.)
No output buffering The php.ini directives output_buffering and implicit_flush default to false and
true, respectively. Buffering is still available, but must be explicitly enabled, otherwise output will
always be
No time limit The php.ini directive max_execution_time is set to zero, so scripts will not time out by
default.
No HTML errors In the event you have enabled the php.ini directive html_errors, it will be ignored on
the
command line.
Different php.ini can be loaded. When you are using php from cli it can use different php.ini than web
server do. You can know what file is using by running php --ini.
On either Linux/UNIX or Windows, a script can be passed as an argument to the PHP executable, with
that script's
On Linux/UNIX, the preferred method of running scripts is to use a shebang (e.g. #!/usr/bin/env php)
as the first
line of a file, and set the executable bit on the file. Assuming the script is in your path, you can then
call it directly:
Using /usr/bin/env php makes the PHP executable to be found using the PATH. Following how PHP is
installed, it
might not be located at the same place (such as /usr/bin/php or /usr/local/bin/php), unlike env which
is
On Windows, you could have the same result by adding the PHP's directory and your script to the
PATH and editing
PATHEXT to allow .php to be detected using the PATH. Another possibility is to add a file named
example.bat or
example.cmd in the same directory as your PHP script and write this line into it:
c:\php\php.exe "%~dp0example.php" %*
Or, if you added PHP's directory into the PATH, for convenient use:
php "%~dp0example.php" %*
This example shows the behaviour of getopt when the user input is uncommon:
getopt.php
var_dump(
);
$ php getopt.php -a -a -bbeta -b beta -cgamma --delta --epsilon --zeta --zeta=f -c gamma
array(6) {
["a"]=>
array(2) {
[0]=>
bool(false)
[1]=>
bool(false)
["b"]=>
array(2) {
[0]=>
string(4) "beta"
[1]=>
string(4) "beta"
["c"]=>
array(2) {
[0]=>
string(5) "gamma"
[1]=>
bool(false)
["delta"]=>
bool(false)
["epsilon"]=>
string(6) "--zeta"
["zeta"]=>
string(1) "f"
Individual options (no colon) always carry a boolean value of false if enabled.
If an option is repeated, the respective value in the output of getopt will become an array.
Required argument options (one colon) accept one space or no space (like optional argument options)
as
separator
After one argument that cannot be mapped into any options, the options behind will not be mapped
either.
As from version 5.4, PHP comes with built-in server. It can be used to run application without need to
install other
http server like nginx or apache. Built-in server is designed only in controller environment for
development and
testing purposes.
Now yout should be able to see content in browser. To check this, navigate to http://localhost:8080
GNU gettext is an extension within PHP that must be included at the php.ini:
The gettext functions implement an NLS (Native Language Support) API which can be used to
internationalize your
PHP applications.
Translating strings can be done in PHP by setting the locale, setting up your translation tables and
calling gettext()
<?php
putenv('LC_ALL= fr_FR');
setlocale(LC_ALL, 'fr_FR');
bindtextdomain("myPHPApp", "./locale");
textdomain("myPHPApp");
myPHPApp.po
#: /Hello_world.php:56
msgid "Hello"
msgstr "Bonjour"
#: /Hello_world.php:242
gettext() loads a given post-complied .po file, a .mo. which maps your to-be translated strings as
above.
After this small bit of setup code, translations will now be looked for in the following file:
./locale/fr_FR/LC_MESSAGES/myPHPApp.mo.
Whenever you call gettext('some string'), if 'some string' has been translated in the .mo file, the
translation
Here is a basic setting of the Header to change to a new page when a button is clicked.
if(isset($_REQUEST['action']))
switch($_REQUEST['action'])
break;
case 'getProject':
header("Location: http://NewPageForProject.com/getProject.php?search=" .
$_POST['search']);
break;
else
GetSearchTerm(!NULL);
function GetSearchTerm($success)
if (is_null($success))
//Using the $_SERVER['PHP_SELF'] keeps us on this page till the switch above determines where to
go
</form>";
GetSearchTermProject($success);
function GetSearchTermProject($success)
</form>";
?>
You should always use <?php ?> tags or short-echo tags <?= ?>. Other variations (in particular, short
tags <? ?>)
When a file is not expected to produce output (the entire file is PHP code) the closing ?> syntax should
be omitted
to avoid unintentional output, which can cause problems when a client parses the document, in
particular some
browsers fail to recognise the <!DOCTYPE tag and activate Quirks Mode.
<?php
class Foo
...
<ul id="nav">
</a></li>
</ul>
PHP 5.5 introduces Generators and the yield keyword, which allows us to write asynchronous code
that looks more
The yield expression is responsible for giving control back to the calling code and providing a point of
resumption
at that place. One can send a value along the yield instruction. The return value of this expression is
either null or
// the mere presence of the yield keyword in this function makes this a Generator
do {
$gen = reverse_range(5);
print $gen->current();
foreach ($gen as $val) { // loops over the Generator, resuming it upon each iteration
echo $val;
// Output: 5injected!4321
This mechanism can be used by a coroutine implementation to wait for Awaitables yielded by the
Generator (by
registering itself as a callback for resolution) and continue execution of the Generator as soon as the
Awaitable is
resolved.
use Icicle\Awaitable;
use Icicle\Coroutine\Coroutine;
use Icicle\Loop;
// Sets $start to the value returned by microtime() after approx. $time seconds.
// Throws the exception from the rejected awaitable into the coroutine.
};
// Coroutine sleeps for 1.2 seconds, then will resolve with a string.
});
Loop\run();
proc_open()
PHP has no support for running code concurrently unless you install extensions such as pthread. This
can be
sometimes bypassed by using proc_open() and stream_set_blocking() and reading their output
asynchronously.
If we split code into smaller chunks we can run it as multiple suprocesses. Then using
stream_set_blocking()
function we can make each subprocess also non-blocking. This means we can spawn multiple
subprocesses and
then check for their output in a loop (similarly to an even loop) and wait until all of them finish.
As an example we can have a small subprocess that just runs a loop and in each iteration sleeps
randomly for 100 -
1000ms (note, the delay is always the same for one subprocess).
<?php
// subprocess.php
$name = $argv[1];
usleep($delay * 1000);
printf("$name: $i\n");
Then the main process will spawn subprocesses and read their output. We can split it into smaller
blocks:
Properly close file handles with the output pipe for each subprocess using fclose() and close process
<?php
// non-blocking-proc_open.php
$descriptors = [
];
$pipes = [];
$processes = [];
// Spawn a subprocess.
$processes[$i] = $proc;
stream_set_blocking($procPipes[1], 0);
$pipes[$i] = $procPipes;
if ($str) {
printf($str);
fclose($pipes[$i][1]);
proc_close($processes[$i]);
The output then contains mixture from all three subprocesses as they we're read by fread() (note, that
in this case
$ php non-blocking-proc_open.php
proc1: 0
proc1: 1
proc1: 2
proc1: 3
proc3: 0
proc1: 4
proc2: 0
proc3: 1
proc2: 1
proc3: 2
proc2: 2
proc3: 3
proc2: 3
proc3: 4
proc2: 4
Section 70.4: Reading serial port with Event and DIO
DIO streams are currently not recognized by the Event extension. There is no clean way to obtain the
file descriptor
pass the numeric file descriptor to dio_fdopen() (currently undocumented) and get the DIO resource;
add an Event with a callback for listening to the read events on the file descriptor;
in the callback drain the available data and process it according to the logic of your application.
dio.php
<?php
class Scanner {
$this->port = $port;
$this->base->exit();
if ($this->e_open)
$this->e_open->free();
if ($this->e_read)
$this->e_read->free();
if ($this->dio)
dio_close($this->dio);
stream_set_blocking($stream, false);
$this->fd = EventUtil::getSocketFd($stream);
if ($this->fd < 0) {
return;
$this->e_open->add();
$this->base->dispatch();
fclose($stream);
$this->e_open->del();
$this->dio = dio_fdopen($this->fd);
dio_tcsetattr($this->dio, [
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
]);
[$this, '_onRead']);
$this->e_read->add();
var_dump($data);
$scanner->run();
Testing
2016/12/01 18:04:06 socat[16750] N starting data transfer loop with FDs [5,5] and [7,7]
The output may be different. Use the PTYs from the first couple of rows (/dev/pts/5 and /dev/pts/8, in
particular).
In terminal B run the above-mentioned script. You may need root privileges:
Output:
string(1) "t"
string(1) "e"
string(1) "s"
string(1) "t"
string(1) "
"
The class allows to schedule a number of HTTP requests, then run them asynchronously.
http-client.php
<?php
class MyHttpClient {
protected $base;
}
/**
* @return void
*/
$this->base->dispatch();
$this->connections = null;
/**
* @return EventHttpRequest|false
*/
public function addRequest($address, $port, array $headers,
$conn->setTimeout(5);
return $req;
return false;
/**
* @return void
*/
public function _requestHandler($req, $unused) {
if (is_null($req)) {
} else {
$response_code = $req->getResponseCode();
if ($response_code == 0) {
} else {
$buf = $req->getInputBuffer();
echo "Body:\n";
$address = "my-host.local";
$port = 80;
$client->run();
test.php
<?php
Usage
php http-client.php
Sample Output
Success: 200
Body:
GET: array (
User-Agent: My-User-Agent/1.0
Success: 200
Body:
GET: array (
User-Agent: My-User-Agent/1.0
Success: 200
Body:
GET: array (
...
(Trimmed.)
Note, the code is designed for long-term processing in the CLI SAPI.
Ev extension implements a simple yet powerful general purpose event loop. It doesn't provide
network-specific
watchers, but its I/O watcher can be used for asynchronous processing of sockets.
The following code shows how HTTP requests can be scheduled for parallel processing.
http-client.php
<?php
class MyHttpRequest {
private $http_client;
private $address;
private $resource;
/// @var string HTTP method such as GET, POST etc.
private $method;
private $service_port;
private $socket;
private $timeout_watcher;
private $write_watcher;
private $read_watcher;
private $conn_watcher;
private $buffer;
115, // EINPROGRESS
];
/**
* @param string $method HTTP method: GET, HEAD, POST, PUT etc.
* @throws RuntimeException
*/
$this->http_client = $client;
$this->host = $host;
$this->resource = $resource;
$this->method = $method;
$this->address = gethostbyname($this->host);
if (!$this->socket) {
socket_strerror(socket_last_error()));
socket_set_nonblock($this->socket);
$this->conn_watcher = $this->http_client->getLoop()
$this->close();
if ($w) {
$w->stop();
$w = null;
/**
*/
if ($this->socket) {
socket_close($this->socket);
$this->socket = null;
$this->freeWatcher($this->timeout_watcher);
$this->freeWatcher($this->read_watcher);
$this->freeWatcher($this->write_watcher);
$this->freeWatcher($this->conn_watcher);
}
/**
* @return bool
*/
$loop = $this->http_client->getLoop();
/**
*/
$w->stop();
$this->close();
/**
*/
$this->timeout_watcher->stop();
$w->stop();
$in = implode("\r\n", [
"{$this->method} {$this->resource} HTTP/1.1",
"Host: {$this->host}",
'Connection: Close',
]) . "\r\n\r\n";
return;
$loop = $this->http_client->getLoop();
$this->read_watcher = $loop->io($this->socket,
$loop->run();
/**
*/
if ($ret) {
// Still have data to read. Append the read chunk to the buffer.
$this->buffer .= $out;
// All is read
printf("\n<<<<\n%s\n>>>>", rtrim($this->buffer));
fflush(STDOUT);
$w->stop();
$this->close();
return;
if (in_array(socket_last_error(), static::$e_nonblocking)) {
return;
$w->stop();
$this->close();
/////////////////////////////////////
class MyHttpClient {
private $loop;
}
public function __destruct() {
$this->loop->stop();
/**
* @return EvLoop
*/
return $this->loop;
/**
*/
/**
*/
$this->loop->run();
/////////////////////////////////////
// Usage
$client->run();
Testing
<?php
Then the output of php http-client.php command will be similar to the following:
<<<<
HTTP/1.1 200 OK
Server: nginx/1.10.1
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo
1d
GET: array (
>>>>
<<<<
HTTP/1.1 200 OK
Server: nginx/1.10.1
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo
1d
GET: array (
>>>>
...
(trimmed)
Note, in PHP 5 the sockets extension may log warnings for EINPROGRESS, EAGAIN, and EWOULDBLOCK
errno values. It is
error_reporting(E_ERROR);
Amp harnesses Promises [another name for Awaitables] and Generators for coroutine creation.
use Amp\Dns;
function queryStackOverflow($recordtype) {
$requests = [
Dns\query("stackoverflow.com", $recordtype),
];
// returns a Promise resolving when the first one of the requests resolves
try {
$promise = Amp\resolve(queryStackOverflow(Dns\Record::NS));
echo "The result of the fastest server to reply to our query was $ns";
});
Address
In the light of the latest httpoxy vulnerabilities, there is another variable, that is widely misused.
HTTP_X_FORWARDED_FOR is often used to detect the client IP address, but without any additional
checks, this can lead
to security issues, especially when this IP is later used for authentication or in SQL queries without
sanitization.
Most of the code samples available ignore the fact that HTTP_X_FORWARDED_FOR can actually be
considered as
information provided by the client itself and therefore is not a reliable source to detect clients IP
address. Some of
the samples do add a warning about the possible misuse, but still lack any additional check in the code
itself.
So here is an example of function written in PHP, how to detect a client IP address, if you know that
client may be
behind a proxy and you know this proxy can be trusted. If you don't known any trusted proxies, you
can just use
REMOTE_ADDR
function get_client_ip()
if (!isset($_SERVER['REMOTE_ADDR'])) {
return NULL;
// the original IP
$proxy_header = "HTTP_X_FORWARDED_FOR";
if (array_key_exists($proxy_header, $_SERVER)) {
// Header can contain multiple IP-s of proxies that are passed through.
// Only the IP added by the last proxy (last IP in the list) can be trusted.
if (filter_var($client_ip, FILTER_VALIDATE_IP)) {
return $client_ip;
} else {
return $_SERVER['REMOTE_ADDR'];
print get_client_ip();
<?php
pdf_begin_page($pdf, (72 * 8.5), (72 * 11)); //specify page width and height
$length = strlen($document); $filename = "HelloWorld.pdf"; //Finds PDF length and assigns file name
header("Content-Type:application/pdf");
header("Content-Length:" . $length);
?>
YAML does not come with a standard PHP installation, instead it needs to be installed as a PECL
extension. On
linux/unix it can be installed with a simple
Note that libyaml-dev package must be installed on the system, as the PECL package is simply a
wrapper around
libYAML calls.
Installation on Windows machines is different - you can either download a pre-compiled DLL or build
from sources.
YAML provides a way to store structured data. The data can be a simple set of name-value pairs or a
complex
database:
driver: mysql
host: database.mydomain.com
port: 3306
db_name: sample_db
user: myuser
password: Passw0rd
debug: true
country: us
Let's say, it's saved as config.yaml. Then to read this file in PHP the following code can be used:
$config = yaml_parse_file('config.yaml');
print_r($config);
Array
(
[database] => Array
[debug] => 1
[country] => us
$dbConfig = $config['database'];
$connectString = $dbConfig['driver']
. ":host={$dbConfig['host']}"
. ":port={$dbConfig['port']}"
. ":dbname={$dbConfig['db_name']}"
. ":user={$dbConfig['user']}"
. ":password={$dbConfig['password']}";
Saving to a file
If you want to save the image to a file, you can pass the filename, or an opened file stream, as $to. If
you pass a
stream, you don't need to close it, because GD will automatically close it.
imagepng($image, "/path/to/target/file.png");
imagepng($image2, $stream);
// Don't fclose($stream)
When using fopen, make sure to use the b flag rather than the t flag, because the file is a binary
output.
Do not try to pass fopen("php://temp", $f) or fopen("php://memory", $f) to it. Since the stream is
closed by
the function after the call, you will be unable to use it further, such as to retrieve its contents.
If you want to directly return this image as the response of the image (e.g. to create dynamic badges),
you don't
need to pass anything (or pass null) as the second argument. However, in the HTTP response, you need
to specify
header("Content-Type: $mimeType");
$mimeType is the MIME type of the format you are returning. Examples include image/png, image/gif
and
image/jpeg.
ob_start();
$binary = ob_get_clean();
You may have many reasons that you don't want to use output buffering. For example, you may
already have OB
Using the stream_wrapper_register function, a new stream wrapper can be registered. Hence, you can
pass a
<?php
class GlobalStream{
private $var;
return true;
$this->var .= $data;
return strlen($data);
stream_wrapper_register("global", GlobalStream::class);
$image = imagecreatetruecolor(100, 100);
imagepng($image, $stream);
echo base64_encode($myImage);
In this example, the GlobalStream class writes any input into the reference variable (i.e. indirectly
write to the global
variable of the given name). The global variable can later be retrieved directly.
A fully implemented stream wrapper class should look like this, but according to tests with the __call
magic
method, only stream_open, stream_write and stream_close are called from internal functions.
No flags are required in the fopen call, but you should at least pass an empty string. This is because
the
fopen function expects such parameter, and even if you don't use it in your stream_open
implementation, a
Example usage
In the <img> HTML tag, an image can be directly provided rather than using an external link:
$img is now a resource variable for an image resource with $widthx$height pixels. Note that width
counts from left
to right, and height counts from top to bottom.
Image resources can also be created from image creation functions, such as:
imagecreatefrompng
imagecreatefromjpeg
Image resources may be freed later when there are no more references to them. However, to free the
memory
immediately (this may be important if you are processing many large images), using imagedestroy() on
an image
imagedestroy($image);
Converting an image
Images created by image conversion does not modify the image until you output it. Therefore, an
image converter
$im = imagecreatefromjpeg($filename);
imagepng($im, $outputFile);
imagedestroy($im);
If you have an image and want to create a new image, with new dimensions, you can use
imagecopyresampled
function:
// new image
$dst_img = imagecreatetruecolor($width, $height);
and store the original image into a variable. To do so, you may use one of the createimagefrom*
functions where *
stands for:
jpeg
gif
png
string
For example:
//original image
$src_img=imagecreatefromstring(file_get_contents($original_image_path));
Now, copy all (or part of) original image (src_img) into the new image (dst_img) by
imagecopyresampled:
imagecopyresampled($dst_img, $src_img,
Now, if you want to copy entire of source (initial) image, into entire of destination area (no cropping):
Installation
To see the dependencies installed using the brew method, visit brewformulas.org/Imagemagick.
Usage
<?php
$imagen->thumbnailImage(100, 0);
echo $imagen;
?>
This example is how to turn an image into a Base64 string (i.e. a string you can use directly in a src
attribute of an
img tag). This example specifically uses the Imagick library (there are others available, such as GD as
well).
<?php
/**
* The filename path is releative to the .php file containing this code, so
* in this example, image.jpg should live in the same directory as our script.
*/
/**
* This resizes the image, to the given size in the form of width, height.
* If you want to change the resolution of the image, rather than the size
* Note that for the second parameter, you can set it to 0 to maintain the
*/
$img->resizeImage(320, 240);
/**
*/
$imgBuff = $img->getimageblob();
/**
* This clears the image.jpg resource from our $img object and destroys the
* object. Thus, freeing the system resources allocated for doing our image
* manipulation.
*/
$img->clear();
/**
* This creates the base64 encoded version of our unencoded string from
* earlier. It is then output as an image to the page.
* Note, that in the src attribute, the image/jpeg part may change based on
*/
$img = base64_encode($imgBuff);
function test($x)
return $x;
$server->addFunction("test");
$server->handle();
Classification in Machine Learning is the problem that identifies to which set of categories does a new
observation
Naive Bayes
The train and predict method are same for all classifiers. The only difference would be in the
underlying
algorithm used.
Before we can start with predicting a new observation, we need to train our classifier. Consider the
following code
// Import library
use Phpml\Classification\SVC;
use Phpml\SupportVectorMachine\Kernel;
$samples = [[1, 3], [1, 4], [2, 4], [3, 1], [4, 1], [4, 2]]; // Training samples
$classifier->train($samples, $labels);
The code is pretty straight forward. $cost used above is a measure of how much we want to avoid
misclassifying
each training example. For a smaller value of $cost you might get misclassified examples. By default it
is set to 1.0
Now that we have the classifier trained we can start making some actual predictions. Consider the
following codes
k-Nearest Neighbors
The classfier for this algorithm takes in two parameters and can be initialized like
$neighbor_num is the number of nearest neighbours to scan in knn algorithm while the second
parameter is
distance metric which by default in first case would be Euclidean. More on Minkowski can be found
here.
// Training data
$samples = [[1, 3], [1, 4], [2, 4], [3, 1], [4, 1], [4, 2]];
// Initialize classifier
// Train classifier
$classifier->train($samples, $labels);
// Make predictions
NaiveBayes Classifier
NaiveBayes Classifier is based on Bayes' theorem and does not need any parameters in constructor.
// Training data
$samples = [[5, 1, 1], [1, 5, 1], [1, 1, 5]];
// Initialize classifier
// Train classifier
$classifier->train($samples, $labels);
// Make predictions
Practical case
Till now we only used arrays of integer in all our case but that is not the case in real life. Therefore let
me try to
Suppose you have an application that stores characteristics of flowers in nature. For the sake of
simplicity
we can consider the color and length of petals. So there two characteristics would be used to train our
data. color is the simpler one where you can assign an int value to each of them and for length, you
can
have a range like (0 mm,10 mm)=1 , (10 mm,20 mm)=2. With the initial data train your classifier. Now
one
of your user needs identify the kind of flower that grows in his backyard. What he does is select the
color
of the flower and adds the length of the petals. You classifier running can detect the type of flower
In classification using PHP-ML we assigned labels to new observation. Regression is almost the same
with difference
being that the output value is not a class label but a continuous value. It is widely used for predictions
and
Regression has the same train and predict methods as used in classification.
This is the regression version for SVM(Support Vector Machine).The first step like in classification is to
train our
model.
// Import library
use Phpml\Regression\SVR;
use Phpml\SupportVectorMachine\Kernel;
// Training data
$regression->train($samples, $targets);
In regression $targets are not class labels as opposed to classification. This is one of the differentiating
factor for
the two. After training our model with the data we can start with the actual predictions
// Training data
// Train engine
$regression->train($samples, $targets);
PHP-ML also provides with the option of Multiple Linear Regression. A sample code for the same can
be as
follows
$samples = [[73676, 1996], [77006, 1998], [10565, 2000], [146088, 1995], [15000, 2001], [65940,
2000], [9300, 2000], [93739, 1996], [153260, 1994], [17764, 2002], [57000, 1998], [15000, 2000]];
$targets = [2000, 2750, 15500, 960, 4400, 8800, 7100, 2550, 1025, 5900, 4600, 4400];
$regression->train($samples, $targets);
Multiple Linear Regression is particularly useful when multiple factors or traits identify the outcome.
Practical case
Suppose you run a very popular website, but the traffic keeps on changing. You want a solution that
would predict the number of servers you need to deploy at any given instance of time. Lets assume for
the sake that your hosting provider gives you an api to spawn out servers and each server takes 15
minutes to boot. Based on previous data of traffic, and regression you can predict the traffic that
would
hit your application at any instance of time. Using that knowledge you can start a server 15 minutes
before the surge thereby preventing your application from going offline.
Clustering is about grouping similar objects together. It is widely used for pattern recognition.
Clustering comes
under unsupervised machine learning, therefore there is no training needed. PHP-ML has support for
the
k-Means
dbscan
k-Means
k-Means separates the data into n groups of equal variance. This means that we need to pass in a
number n which
would be the number of clusters we need in our solution. The following code will help bring more
clarity
$samples = [[1, 1], [8, 7], [1, 2], [7, 8], [2, 1], [8, 9]];
Note that the output contains 3 arrays because because that was the value of n in KMeans
constructor. There can
also be an optional second parameter in the constructor which would be the initialization method. For
example
consider
INIT_RANDOM places a completely random centroid while trying to determine the clusters. But just to
avoid the
centroid being too far away from the data, it is bound by the space boundaries of data.
The default constructor initialization method is kmeans++ which selects centroid in a smart way to
speed up the
process.
DBSCAN
As opposed to KMeans, DBSCAN is a density based clustering algorithm which means that we would
not be passing n
which would determine the number of clusters we want in our result. On the other hand this requires
two
parameters to work
2. $epsilon : Which is the maximum distance between two samples for them to be considered as in the
same
cluster.
$samples = [[1, 1], [8, 7], [1, 2], [7, 8], [2, 1], [8, 9]];
The code is pretty much self explanatory. One major difference is that there is no way of knowing the
number of
Practical Case
Let us now have a look on using clustering in real life scenario
Clustering is widely used in pattern recognition and data mining. Consider that you have a content
publishing application. Now in order to retain your users they should look at content that they love.
Let us
assume for the sake of simplicity that if they are on a specific webpage for more that a minute and
they
scoll to bottom then they love that content. Now each of your content will be having a unique
identifier
with it and so will the user. Make cluster based on that and you will get to know which segment of
users
have a similar content taste. This in turn could be used in recommendation system where you can
assume that if some users of same cluster love the article then so will others and that can be shown as
Memcache is a distributed object caching system and uses key-value for storing small data. Before you
start calling
Memcache code into PHP, you need to make sure that it is installed. That can be done using
class_exists method in
php. Once it is validated that the module is installed, you start with connecting to memcache server
instance.
if (class_exists('Memcache')) {
$cache->connect('localhost',11211);
}else {
}
This will validate that Memcache php-drivers are installed and connect to memcache server instance
running on
localhost.
In the example above we only connected to a single instance, but you can also connect to multiple
servers using
if (class_exists('Memcache')) {
$cache->addServer('192.168.0.100',11211);
$cache->addServer('192.168.0.101',11211);
Note that in this case unlike connect , there won't be any active connection until you try to store or
fetch a value.
Store data
$cache or memcached class object has a set method that takes in a key,value and time to save the
value for (ttl).
Here $ttl or time to live is time in seconds that you want memcache to store the pair on server.
Get data
$cache or memcached class object has a get method that takes in a key and returns the corresponding
value.
$value = $cache->get($key);
In case there is no value set for the key it will return null
GoalKicker.com – PHP Notes for Professionals 378
Delete data
Sometimes you might have the need to delete some cache value.$cache or memcache instance has a
delete
$cache->delete($key);
Let us assume a simple blog. It will be having multiple posts on landing page that get fetched from
database with
each page load. In order to reduce the sql queries we can use memcached to cache the posts. Here is a
very small
implementation
if (class_exists('Memcache')) {
$cache->connect('localhost',11211);
// Cache hit
} else {
// Cache miss
$cache->set('posts', $posts,0,$ttl);
}else {
}
Section 78.2: Cache Using APC Cache
The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. Its goal is to provide a free,
open, and
installation
Add Cache:
Delete Cache:
apc_delete($key);
if (apc_exists($key)) {
echo apc_fetch($key);
} else {
Performance:
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
// Ruminant.php
parent::eats($food);
} else {
// Cow.php
}
// pasture.php
require 'autoload.php';
$animal->eats('grass');
Thanks to our generic autoloader, we have access to any class that follows our autoloader naming
convention. In
this example, our convention is simple: the desired class must have a file in the same directory named
for the class
and ending in ".php". Notice that the class name exactly matches the file name.
Without autoloading, we would have to manually require base classes. If we built an entire zoo of
animals, we'd
have thousands of require statements that could more easily be replaced with a single autoloader.
In the final analysis, PHP autoloading is a mechanism to help you write less mechanical code so you
can focus on
solving business problems. All you have to do is define a strategy that maps class name to file name.
You can roll your
own autoloading strategy, as done here. Or, you can use any of the standard ones the PHP community
has
adopted: PSR-0 or PSR-4. Or, you can use composer to generically define and manage these
dependencies.
// zoo.php
class Animal {
$animal->eats('meat');
PHP knows what Animal is before executing new Animal, because PHP reads source files top-to-
bottom. But what if
we wanted to create new Animals in many places, not just in the source file where it's defined? To do
that, we need
// Animal.php
class Animal {
// zoo.php
require 'Animal.php';
$animal->eats('slop');
// aquarium.php
require 'Animal.php';
$animal->eats('shrimp');
Here we have three files. One file ("Animal.php") defines the class. This file has no side effects besides
defining the
class and neatly keeps all the knowledge about an "Animal" in one place. It's easily version controlled.
It's easily
reused.
Two files consume the "Animal.php" file by manually require-ing the file. Again, PHP reads source files
top-tobottom, so the require goes and finds the "Animal.php" file and makes the Animal class
definition available before
Now imagine we had dozens or hundreds of cases where we wanted to perform new Animal. That
would require
(pun-intended) many, many require statements that are very tedious to code.
loading
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
// zoo.php
require 'autoload.php';
$animal->eats('slop');
// aquarium.php
require 'autoload.php';
Compare this to the other examples. Notice how require "Animal.php" was replaced with require
"autoload.php". We're still including an external file at run-time, but rather than including a specific
class definition
we're including logic that can include any class. It's a level of indirection that eases our development.
Instead of
writing one require for every class we need, we write one require for all classes. We can replace N
require with 1
require.
The magic happens with spl_autoload_register. This PHP function takes a closure and adds the closure
to a queue of
closures. When PHP encounters a class for which it has no definition, PHP hands the class name to
each closure in
the queue. If the class exists after calling a closure, PHP returns to its previous business. If the class
fails to exist
after trying the entire queue, PHP crashes with "Class 'Whatever' not found."
You might simply include this file and you will get autoloading for free.
You can also add your own code to the Autoloader by adding an autoload section to your
composer.json.
"autoload": {
}
In this section you define the autoload mappings. In this example its a PSR-4 mapping of a namespace
to a
directory: the /src directory resides in your projects root folder, on the same level as the /vendor
directory is. An
Important: After adding new entries to the autoload section, you have to re-run the command dump-
autoload to
re-generate and update the vendor/autoload.php file with the new information.
In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and files autoloading. See
the
When you including the /vendor/autoload.php file it will return an instance of the Composer
Autoloader. You
might store the return value of the include call in a variable and add more namespaces. This can be
useful for
$loader->add('Application\\Test\\', __DIR__);
PHP's default Array type is actually implemented as ordered hash maps, which allow us to create
arrays that consist
of key/value pairs where values can be of any type and keys can be either numbers or strings. This is
not
So as you can see from this illustration a normal PHP array can be viewed more like an an ordered set
of key/value
pairs, where each key can map to any value. Notice in this array we have keys that are both numbers
and strings, as
well as values of different types and the key has no bearing on the order of the elements.
$arr = [
9 => "foo",
1 => 4.2,
];
Regular PHP arrays are also dynamically sized for us. They grow and shrink as we push and pop values
to and from
However, in a traditional array the size is fixed and consists entirely of the same type of value. Also,
rather than
keys each value is access by its index, which can be deduced by its offset in the array.
Since we would know the size of a given type and the fixed size of the array an offset is then the type
size * n
were n represents the value's position in the array. So in the example above $arr[0] gives us 1, the first
element in
SplFixedArray, however, doesn't restrict the type of values. It only restricts the keys to number types.
It's also of a
fixed size.
This makes SplFixedArrays more efficient than normal PHP arrays in one particular way. They are more
compact so
SplFixedArray is implemented as an object, but it can be accessed with the same familiar syntax that
you access a
normal PHP array since they implement the ArrayAccess interface. They also implement Countable
and Iterator
interfaces so they behave the same way you'd be used to arrays behaving in PHP (i.e. things like
count($arr) and
foreach($arr as $k => $v) work the same way for SplFixedArray as they do normal arrays in PHP.
The SplFixedArray constructor takes one argument, which is the size of the array.
$arr[0] = "foo";
$arr[1] = "bar";
$arr[2] = "baz";
var_dump(count($arr));
Gives us...
int(4)
Notice in SplFixedArray, unlike a normal PHP Array, the key does depict the order of the element in our
array,
Just keep in mind that because the array is of a fixed size, count will always return the same value. So
while
So to resize the array you will need to call on the setSize method.
$arr->setSize(3);
var_dump(count($arr));
Now we get...
int(3) 0 => foo 1 => 2 => baz Import to SplFixedArray & Export from SplFixedArray
You can also import/export a normal PHP Array into and out of an SplFixedArray with the fromArray
and toArray
methods.
$array = [1,2,3,4,5];
$fixedArray = SplFixedArray::fromArray($array);
foreach($fixedArray as $value) {
12345
$fixedArray[1] = 2;
$fixedArray[2] = 3;
$fixedArray[3] = 4;
$fixedArray[4] = 5;
$array = $fixedArray->toArray();
foreach($array as $value) {
12345
To do anything with an IMAP account you need to connect to it first. To do this you need to specify
some required
parameters:
imap,
pop3,
nntp, smtp
imap
/authuser=user
/novalidate-cert do not validate certificates from TLS/SSL server, needed if server uses selfsigned
certificates. USE WITH CAUTION disabled
/tls force use of start-TLS to encrypt the session, and reject connection to
/notls do not do start-TLS to encrypt the session, even with servers that support
it
/readonly request read-only mailbox open (IMAP only; ignored on NNTP, and an
{imap.example.com:993/imap/tls/secure}
Please note that if any of the characters in your connection string is non-ASCII it must be encoded with
utf7_encode($string).
To connect to the mailbox, we use the imap_open command which returns a resource value pointing
to a stream:
<?php
To use the IMAP functions in PHP you'll need to install the IMAP extension:
Once you've connected to your mailbox, you'll want to take a look inside. The first useful command is
imap_list. The
first parameter is the resource you acquired from imap_open, the second is your mailbox string and
the third is a
} else {
print_r($folders);
Array
You can use the third parameter to filter these results like this:
And now the result only contains entries with .Sent in the name:
Array
Note: Using * as a fuzzy search will return all matches recursively. If you use % it will return only
matches in the
You can return a list of all the messages in a mailbox using imap_headers.
<?php
$headers = imap_headers($mailbox);
Note that this call could take a fair amount of time to run and may return a very large list.
An alternative is to load individual messages as you need them. Your emails are each assigned an ID
from 1 (the
There are a number of functions to access an email directly, but the simplest way is to use
imap_header which
<?php
[Recent] =>
[Unseen] =>
[Flagged] =>
[Answered] =>
[Deleted] =>
[Draft] =>
[Msgno] => 1
PLEASE NOTE: ONLY PUT THIS CODE IN THE HEADER OF THE PAGE, OTHERWISE IT WILL NOT WORK!
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
exit;
?>
//You html page
Usage of socket extension implements a low-level interface to the socket communication functions
based on the
popular BSD sockets, providing the possibility to act as a socket server as well as a client.
Create a websocket script that listens to Port 5000 Use putty, terminal to run telnet 127.0.0.1 5000
(localhost).
This script replies with the message you sent (as a ping-back)
<?php
// Settings
$address = '127.0.0.1';
$port = 5000;
/*
$domain can be AF_INET, AF_INET6 for IPV6 , AF_UNIX for Local communication protocol
*/
}
/*
*/
do {
break;
do {
break 2;
if (!$buf = trim($buf)) {
continue;
echo "$buf\n";
} while (true);
socket_close($msgsock);
} while (true);
socket_close($socket);
?>
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place which will be used in
the
comparison.
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place in the result.
scale A optional parameter to set the number of digits after the decimal place in the result.
The Binary Calculator can be used to calculate with numbers of any size and precision up to
2147483647-1
decimals, in string format. The Binary Calculator is more precise than the float calculation of PHP.
bit system
On 32-bit systems, integers greater than 0x7FFFFFFF cannot be stored primitively, while integers
between
0x0000000080000000 and 0x7FFFFFFFFFFFFFFF can be stored primitively on 64-bit systems but not 32-
bit systems
(signed long long). However, since 64-bit systems and many other languages support storing signed
long long
integers, it is sometimes necessary to store this range of integers in exact value. There are several ways
to do so,
such as creating an array with two numbers, or converting the integer into its decimal human-readable
form. This
has several advantages, such as the convenience in presenting to the user, and the ability to
manipulate it with
bcmath directly.
The pack/unpack methods can be used to convert between binary bytes and decimal form of the
numbers (both of
type string, but one is binary and one is ASCII), but they will always try to cast the ASCII string into a
32-bit int on
// remember to add the quotes, or the number will be parsed as a float literal
$result = "0";
// 9223372036854775808 is equal to (1 << 63) (note that this expression actually does not work
return $result;
arithmetic operations
bcadd vs float+float
bcsub vs float-float
bcmul vs int*int
bcmul vs float*float
bcdiv vs float/float
Docker is a very popular container solution being used widely for deploying code in production
environments. It
In order to deploy the application on docker, first we need to get the image from registry.
This will get you the latest version of image from official php repository. Generally speaking, PHP is
usually used to
deploy web-applications so we need an http server to go with the image. php:7.0-apache image comes
preinstalled with apache to make deployment hastle free.
Dockerfile is used to configure the custom image that we will be building with the web-application
codes. Create a
new file Dockerfile in the root folder of project and then put the following contents in the same
FROM php:7.0-apache
COPY . /var/www/html/
EXPOSE 80
The first line is pretty straight forward and is used to describe which image should be used to build out
new image.
The same could be changed to any other specific version of PHP from the registry.
Second line is simply to upload php.ini file to our image. You can always change that file to some other
custom file
location.
The third line would copy the codes in current directory to /var/www/html which is our webroot.
Remember
The last line would simply open up port 80 inside the docker container.
Ignoring files
In some instances there might be some files that you don't want on server like environment
configuration etc. Let
us assume that we have our environment in .env. Now in order to ignore this file, we can simply add it
to
Building image is not something specific to php, but in order to build the image that we described
above, we can
simply use
Once the image is built, you can verify the same using
docker images
Which would list out all the images installed in your system.
Once we have an image ready, we can start and serve the same. In order to create a container from
the image, use
that the container should run as background job. The final specifies which image should be used to
build the
container.
Checking container
docker ps
This will list out all the containers running on docker daemon.
Application logs
Logs are very important to debug the application. In order to check on them use
APCu is a shared memory key-value store for PHP. The memory is shared between PHP-FPM processes
of the same
print_r($entry);
The iterator can be initialized with an optional regular expression to select only entries with matching
keys:
print_r($entry);
}
Information about a single cache entry can be obtained via:
$key = '…';
print_r((new APCUIterator($regex))->current());
$key = 'Hello';
$value = 'World';
apcu_store($key, $value);
print(apcu_fetch('Hello')); // 'World'
print_r(apcu_cache_info());
Note that invoking apcu_cache_info() without limit will return the complete data currently stored.
Column Column
-t Public directory
Learn how to use the built in server to develop and test your application without the need of other
tools like xamp,
wamp, etc.
Section 87.1: Running the built in server
php -S localhost:80
Listening on http://localhost:80
This is the simplest way to start a PHP server that responds to request made to localhost at the port
80.
The localhost:80 indicates the host that we are answering and the port. You can use other
combinations like:
script
Listening on http://localhost:80
The PSR (PHP Standards Recommendation) is a series of recommendations put together by the FIG
(Framework
Interop Group).
"The idea behind the group is for project representatives to talk about the commonalities between
our projects and
find ways we can work together" - FIG FAQ
PSR-4 is an accepted recommendation that outlines the standard for autoloading classes via
filenames. This
recommendation is recommended as the alternative to the earlier (and now deprecated) PSR-0.
The fully qualified class name should match the following requirement:
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
Thus the final class name would be Alphabet\Google\AdWord\KeywordPlanner. The fully qualified
class name
located in [path_to_source]/Alphabet/Google/AdWord/KeywordPlanner.php
Starting with PHP 5.3.0, a custom autoloader function can be defined to load files based on the path
and filename
Replacing the location ('classes/') and filename extension ('.class.php') with values that apply to your
structure.
Composer package manager supports PSR-4 which means, if you follow the standard, you can load
your classes in
{
"autoload": {
"psr-4": {
"Alphabet\\": "[path_to_source]"
$ composer dump-autoload
<?php
PSR-1 is an accepted recommendation and outlines a basic standard recommendation for how code
should be
written.
It indicates which PHP tags to use: <?php and <?= but not <?.
It also states that files should either declare new symbols (classes, functions, constants, etc.) and
cause no
other side effects, or execute logic with side effects and not define symbols, but do both.
The @var keyword can be used to describe the type and usage of:
a class property
class Example {
public $some_str;
/**
*/
...
The type can be one of the built-in PHP types, or a user-defined class, including namespaces.
The name of the variable should be included, but can be omitted if the docblock applies to only one
item.
Function level annotations help IDEs identify return values or potentially dangerous code
/**
* @return Int
*/
/**
*/
function dangerousCode()
/**
* @deprecated
*/
function oldCode()
/**
* Parameters
*/
/**
*/
/**
* Parameters - Arrays
*/
/**
* Parameters - Complex
* <pre>
* $params = [
*]
* </pre>
*/
function demo_param_complex($config)
Generics Syntax
Type[]
Type<Type>
Type<Type[, Type]...>
Type<Type[|Type]...>
Values in a Collection MAY even be another array and even another Collection.
Type<Type<Type>>
Type<Type<Type[, Type]...>>
Type<Type<Type[|Type]...>>
Examples
<?php
/**
*/
/**
*/
/**
*/
$name = new ArrayObject([
new stdClass(),
new stdClass()
]);
/**
*/
'a',
true,
1,
'b',
new stdClass(),
'c',
]);
/**
*/
]);
/**
* @var ArrayObject<int, string> $name
*/
1 => 'a',
2 => 'b'
]);
/**
*/
'a' => 1,
'b' => 2
]);
/**
*/
]);
File level metadata applies to all the code within the file and should be placed at the top of the file:
<?php
/**
*/
If a class extends another class and would use the same metadata, providing it @inheritDoc is a simple
way for use
the same documentation. If multiple classes inherit from a base, only the base would need to be
changed for the
children to be affected.
/**
* @return Int
*/
/**
* @inheritDoc
*/
return $a + $b;
This topic provides examples of well known design patterns implemented in PHP.
Method Chaining is a technique explained in Martin Fowler's book Domain Specific Languages.
Method Chaining is
summarized as
Makes modifier methods return the host object, so that multiple modifiers can be invoked in a single
expression.
Consider this non-chaining/regular piece of code (ported to PHP from the aforementioned book)
$hardDrive->setCapacity(150);
$hardDrive->external();
$hardDrive->setSpeed(7200);
Method Chaining would allow you to write the above statements in a more compact way:
->setCapacity(150)
->external()
->setSpeed(7200);
All you need to do for this to work is to return $this in the methods you want to chain from:
class HardDrive {
protected $capacity = 0;
protected $speed = 0;
public function external($isExternal = true) {
$this->isExternal = $isExternal;
return $this; // returns the current class instance to allow method chaining
$this->capacity = $capacity;
return $this; // returns the current class instance to allow method chaining
$this->speed = $speed;
return $this; // returns the current class instance to allow method chaining
When to use it
The primary use cases for utilizing Method Chaining is when building internal Domain Specific
Languages. Method
Chaining is a building block in Expression Builders and Fluent Interfaces. It is not synonymous with
those, though.
I've also noticed a common misconception - many people seem to equate fluent interfaces with
Method
Chaining. Certainly chaining is a common technique to use with fluent interfaces, but true fluency is
much
With that said, using Method Chaining just for the sake of avoiding writing the host object is
considered a code
smell by many. It makes for unobvious APIs, especially when mixing with non-chaining APIs.
Additional Notes
Command Query Separation is a design principle brought forth by Bertrand Meyer. It states that
methods mutating
state (commands) should not return anything, whereas methods returning something (queries) should
not mutate
state. This makes it easier to reason about the system. Method Chaining violates this principle because
we are
Getters
When making use of classes which implement method chaining, pay particular attention when calling
getter
methods (that is, methods which return something other than $this). Since getters must return a value
other than
$this, chaining an additional method onto a getter makes the call operate on the gotten value, not on
the original
object. While there are some use cases for chained getters, they may make code less readable.
Method Chaining as presented above does not violate Law of Demeter. Nor does it impact testing.
That is because
we are returning the host instance and not some collaborator. It's a common misconception stemming
from people
confusing mere Method Chaining with Fluent Interfaces and Expression Builders. It is only when
Method Chaining
returns other objects than the host object that you violate Law of Demeter and end up with Mock
fests in your tests.
To compile a PHP extension in a typical Linux environment, there are a few pre-requisites:
An ANSI C compiler
The source code for the PHP extension you want to compile
Generally there are two ways to compile a PHP extension. You can statically compile the extension into
the PHP
binary, or compile it as a shared module loaded by your PHP binary at startup. Shared modules are
more likely
since they allow you to add or remove extensions without rebuilding the entire PHP binary. This
example focuses
If you installed PHP via your package manager (apt-get install, yum install, etc..) you will need to install
the -
dev package for PHP, which will include the necessary PHP header files and phpize script for the build
environment
to work. The package might be named something like php5-dev or php7-dev, but be sure to use your
package
manager to search for the appropriate name using your distro's repositories. They can differ.
If you built PHP from source the header files most likely already exist on your system (usually in
/usr/include or
/usr/local/include).
Steps to compile
After you check to make sure you have all the prerequisites, necessary to compile, in place you can
head over to
pecl.php.net, select an extension you wish to compile, and download the tar ball.
2. Enter the directory where the archive was unpacked and run phpize
3. You should now see a newly created .configure script if all went well, run that ./configure
4. Now you will need to run make, which will compile the extension
5. Finally, make install will copy the compiled extension binary to your extension directory
The make install step will typically provide the installation path for you where the extension was
copied. This is
usually in /usr/lib/, for example it might be something like /usr/lib/php5/20131226/yaml.so. But this
depends
on your configuration of PHP (i.e. --with-prefix) and specific API version. The API number is included in
the path
To load the extension in PHP, find your loaded php.ini file for the appropriate SAPI, and add the line
extension=yaml.so then restart PHP. Change yaml.so to the name of the actual extension you installed,
of course.
For a Zend extension you do need to provide the full path to the shared object file. However, for
normal PHP
extensions this path derived from the extension_dir directive in your loaded configuration, or from the
$PATH
on line 7
These errors mean that there is something wrong with either your query (this is a PHP/MySQL error),
or your
referencing. The above error was produced by the following code:
$result = $mysqli->query($query);
$row = $result->fetch_assoc();
In order to "fix" this error, it is recommended to make mysql throw exceptions instead:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
This will then throw an exception with this much more helpful message instead:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near 'SELCT * FROM db' at line 1
Another example that would produce a similar error, is where you simply just gave the wrong
information to the
$john = true;
If you get an error like this (or sometimes unexpected $end, depending on PHP version), you will need
to make sure
that you've matched up all inverted commas, all parentheses, all curly braces, all brackets, etc.
<?php
if (true) {
echo "asdf";
?>
Notice the missing curly brace. Also do note that the line number shown for this error is irrelevant - it
always shows
Warnings
T_PAAMAYIM_NEKUDOTAYIM
Appearance:
"Paamayim Nekudotayim" means "double colon" in Hebrew; thus this error refers to the
inappropriate use of the
double colon operator (::). The error is typically caused by an attempt to call a static method that is, in
fact, not
static.
Possible Solution:
$classname::doMethod();
If the above code causes this error, you most likely need to simply change the way you call the
method:
$classname->doMethod();
The latter example assumes that $classname is an instance of a class, and the doMethod() is not a
static method of
that class.
Appearance:
Trying to access an array by a key that does not exist in the array
Possible Solution:
1. isset()
2. array_key_exists()
Appearance:
Happens when your script tries to send a HTTP header to the client but there already was output
before, which
Possible Causes:
1. Print, echo: Output from print and echo statements will terminate the opportunity to send HTTP
headers. The
2. Raw HTML areas: Unparsed HTML sections in a .php file are direct output as well. Script conditions
that will
<!DOCTYPE html>
<?php
3. Whitespace before <?php for "script.php line 1" warnings: If the warning refers to output in line 1,
then it's
mostly leading whitespace, text or HTML before the opening <?php token.
<?php
Reporting
them
If it's not already done in php.ini, error reporting can be set dynamically and should be set to allow
most errors to
be shown:
Syntax
Examples
error_reporting(E_ALL);
// -1 will show every possible error, even when new levels and constants are added
error_reporting(-1);
// without notices
error_reporting(E_WARNING | E_NOTICE);
errors will be logged by default by php, normally in a error.log file at the same level than the running
script.
ini_set('display_errors', 1);
in production however, one should
ini_set('display_errors', 0);
and show a friendly problem message through the use of an Exception or Error handler.
In PHP, a fatal error is a kind of error that cannot be caught, that is, after experiencing a fatal error a
program does
not resume. However, to log this error or somehow handle the crash you can use
register_shutdown_function to
function fatalErrorHandler() {
$error = error_get_last();
// there were no error and shutdown was proper. Also ensure it will handle
return;
// let's naively assume that logs are in the folder inside the app folder.
$type = $error["type"];
$file = $error["file"];
$line = $error["line"];
$message = $error["message"]
fprintf(
$logFile,
date("Y-m-d H:i:s"),
$type,
$message,
$file,
$line);
fclose($logFile);
register_shutdown_function('fatalErrorHandler');
Reference:
http://php.net/manual/en/function.register-shutdown-function.php
http://php.net/manual/en/function.error-get-last.php
http://php.net/manual/en/errorfunc.constants.php
The var_dump function allows you to dump the contents of a variable (type and value) for debugging.
Example:
$array = [3.7, "string", 10, ["hello" => "world"], false, new DateTime()];
var_dump($array);
Output:
array(6) {
[0]=>
float(3.7)
[1]=>
string(6) "string"
[2]=>
int(10)
[3]=>
array(1) {
["hello"]=>
string(5) "world"
[4]=>
bool(false)
[5]=>
object(DateTime)#1 (3) {
["date"]=>
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
You can choose which errors to display, with the error_reporting (or in the ini) function, which accepts
E_*
PHP can display errors in text or HTML format, depending on the html_errors setting.
Example:
ini_set("display_errors", true);
nonexistentFunction(); // E_ERROR
/path/to/file.php:8
Stack trace:
#0 {main}
NOTE: If you have error reporting disabled in php.ini and enable it during runtime, some errors (such
as
parse errors) won't be displayed, because they occurred before the runtime setting was applied.
The common way to handle error_reporting is to enable it fully with E_ALL constant during the
development, and
to disable publicly displaying it with display_errors on production stage to hide the internals of your
scripts.
Warning
It is imperative that phpinfo is only used in a development environment. Never release code
containing
Introduction
Having said that, it can be a useful tool in understanding the PHP environment (OS, configuration,
versions, paths,
modules) in which you are working, especially when chasing a bug. It is a simple built in function:
phpinfo();
It has one parameter $what that allows the output to be customized. The default is INFO_ALL, causing
it to display
all information and is commonly used during development to see the current state of PHP.
You can pass the parameter INFO_* constants, combined with bitwise operators to see a customized
list.
You can run it in the browser for a nicely formatted detailed look. It also works in PHP CLI, where you
can pipe it
Example
This will display a list of PHP directives (ini_get), environment ($_ENV) and predefined variables.
allows to log all function calls, including parameters and return values to a file in different formats
profiling information
remote debugging (provides interface for debugger clients that interact with running PHP scripts)
As you can see this extension is perfectly suited for development environment. Especially remote
debugging
feature can help you to debug your php code without numerous var_dump's and use normal
debugging process as
zend_extension="/usr/local/php/modules/xdebug.so"
ini_set('display_errors', '1');
error_reporting(-1);
Introduction
When working with various libraries and their associated requirements, it is often necessary to know
the version of
This function accepts a single optional parameter in the form of extension name:
phpversion('extension'). If the
extension in question is installed, the function will return a string containing version value. However, if
the
extension not installed FALSE will be returned. If the extension name is not provided, the function will
return the
Example
// or
Let's say, we have a simple LoginForm class with rules() method (used in login page as framework
template):
class LoginForm {
public $email;
public $rememberMe;
public $password;
/* rules() method returns an array with what each field has as a requirement.
* Login form uses email and password to authenticate user.
*/
return [
['email', 'email'],
['rememberMe', 'boolean'],
// Password must match this pattern (must contain only letters and numbers)
];
/** the validate function checks for correctness of the passed rules */
$success = true;
switch ($type) {
case "required":
break;
case "email":
case "boolean":
break;
case "match":
break;
default:
return $success;
In order to perform tests on this class, we use Unit tests (checking source code to see if it fits our
expectations):
protected $loginForm;
/**
* This method belongs to Unit test class LoginFormTest and
*/
$rules = $this->loginForm->rules();
$this->loginForm->email = "valid@email.com";
$this->loginForm->password = "password";
$this->loginForm->rememberMe = true;
invalid");
$this->loginForm->email = '';
(empty)");
$this->loginForm->email = 'invalid.email.com';
format)");
$this->loginForm->email = 'valid@email.com';
$this->loginForm->password = '';
$this->assertFalse($this->loginForm->validate($rules), "Password should not be valid
(empty)");
$this->loginForm->password = 'ThisIsMyPassword';
$this->loginForm->rememberMe = 999;
(integer type)");
$this->loginForm->rememberMe = true;
How exactly Unit tests can help with (excluding general examples) in here? For example, it fits very
well when we
get unexpected results. For example, let's take this rule from earlier:
With dozens of different rules (assuming we are using not just email and password), it's difficult to
detect mistakes.
$this->loginForm->email = "valid@email.com";
$this->loginForm->password = "password";
$this->loginForm->rememberMe = true;
$this->assertTrue($this->loginForm->validate($rules), "Should be valid as nothing is invalid");
Will pass our first example but not second. Why? Because in 2nd example we wrote a pattern with a
typo (missed +
Unit tests can be run in console with command: phpunit [path_to_file]. If everything is OK, we should
be able to
see that all tests are in OK state, else we will see either Error (syntax errors) or Fail (at least one line in
that method
With additional parameters like --coverage we can also see visually how many lines in backend code
were tested
and which passed/failed. This applies to any framework that has installed PHPUnit.
Example how PHPUnit test looks like in console (general look, not according to this example):
Test methods often need data to be tested with. To test some methods completely you need to
provide different
data sets for every possible test condition. Of course, you can do it manually using loops, like this:
...
$data = [...];
foreach($data as $dataSet) {
$this->assertSomething($dataSet);
...
And someone can find it convenient. But there are some drawbacks of this approach. First, you'll have
to perform
additional actions to extract data if your test function accepts several parameters. Second, on failure it
would be
difficult to distinguish the failing data set without additional messages and debugging. Third, PHPUnit
provides
automatic way to deal with test data sets using data providers.
Data provider is a function, that should return data for your particular test case.
A data provider method must be public and either return an array of arrays or an object that
implements the Iterator interface and yields an array for each iteration step. For each array that is part
of the collection the test method will be called with the contents of the array as its arguments.
To use a data provider with your test, use @dataProvider annotation with the name of data provider
function
specified:
/**
* @dataProvider dataProviderForTest
*/
$this->assertEquals($a, $b);
return [
[1,1],
[2,2],
[3,2] //this will fail
];
Array of arrays
Note that dataProviderForTest() returns array of arrays. Each nested array has two elements and they
will fill necessary parameters for testEquals() one by one. Error like this will be thrown Missing
argument 2 for Test::testEquals() if there are not enough elements. PHPUnit will automatically loop
return [
[3,2] // [2] There was 1 failure: 1) Test::testEquals with data set #2 (3, 4)
];
Each data set can be named for convenience. It will be easier to detect failing data:
return [
];
}
Iterators
$this->array = $array;
function rewind() {
return reset($this->array);
function current() {
return current($this->array);
function key() {
return key($this->array);
function next() {
return next($this->array);
function valid() {
...
class Test extends TestCase
/**
* @dataProvider dataProviderForTest
*/
$toCompare = 0;
$this->assertEquals($a, $toCompare);
]);
Note that even for a single parameter, data provider must return an array [$parameter]
Because if we change our current() method (which actually return data on every iteration) to this:
function current() {
return current($this->array)[0];
}
Or change actual data:
]);
1) Warning
Of course, it is not useful to use Iterator object over a simple array. It should implement some specific
Generators
It is not explicitly noted and shown in manual, but you can also use a generator as data provider. Note
that
/**
* @dataProvider fileDataProvider
*/
class Car
/**
* @throws \Exception
*/
}
}
You can do that by enclosing the method call into a try/catch block and making assertions on
execption object's
properties, but more conveniently you can use exception assertion methods. As of PHPUnit 5.2 you
have expectX()
// prepare
$expectedClass = \Exception::class;
$expectedCode = 1;
// test
$this->expectException($expectedClass);
$this->expectMessage($expectedMessage);
$this->expectCode($expectedCode);
// invoke
$car->drive();
If you are using earlier version of PHPUnit, method setExpectedException can be used in stead of
expectX()
methods, but keep in mind that it's deprecated and will be removed in version 6.
// prepare
$expectedClass = \Exception::class;
$expectedCode = 1;
// test
// invoke
$car->drive();
An extension to PHP called Xdebug is available to assist in profiling PHP applications, as well as
runtime debugging.
When running the profiler, the output is written to a file in a binary format called "cachegrind".
Applications are
To enable profiling, install the extension and adjust php.ini settings. In our example we will run the
profile
optionally based on a request parameter. This allows us to keep settings static and turn on the profiler
only as
needed.
// Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger = 1
xdebug.profiler_enable_trigger_value = ""
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"
Next use a web client to make a request to your application's URL you wish to profile, e.g.
http://example.com/article/1?XDEBUG_PROFILE=1
/tmp/cachegrind.out.12345
Note that it will write one file for each PHP request / process that is executed. So, for example, if you
wish to
analyze a form post, one profile will be written for the GET request to display the HTML form. The
XDEBUG_PROFILE
parameter will need to be passed into the subsequent POST request to analyze the second request
which
processes the form. Therefore when profiling it is sometimes easier to run curl to POST a form directly.
Once written the profile cache can be read by an application such as KCachegrind.
Functions executed
Call graphs
Links to source code
Obviously performance tuning is very specific to each application's use cases. In general it's good to
look for:
Repeated calls to the same function you wouldn't expect to see. For functions that process and query
data
Slow-running functions. Where is the application spending most of its time? the best payoff in
performance
tuning is focusing on those parts of the application which consume the most time.
Note: Xdebug, and in particular its profiling features, are very resource intensive and slow down PHP
execution. It is
PHP's runtime memory limit is set through the INI directive memory_limit. This setting prevents any
single
execution of PHP from using up too much memory, exhausting it for other scripts and system software.
The
memory limit defaults to 128M and can be changed in the php.ini file or at runtime. It can be set to
have no limit,
The exact memory usage used during runtime can be determined by calling memory_get_usage(). It
returns the
number of bytes of memory allocated to the currently running script. As of PHP 5.2, it has one
optional boolean
parameter to get the total allocated system memory, as opposed to the memory that's actively being
used by PHP.
<?php
// Outputs 387704
unset($array);
// Outputs 350784
Now memory_get_usage gives you memory usage at the moment it is run. Between calls to this
function you may
allocate and deallocate other things in memory. To get the maximum amount of memory used up to a
certain
<?php
// 385688
// 422736
unset($array);
// 422776
XHProf is a PHP profiler originally written by Facebook, to provide a more lightweight alternative to
XDebug.
After installing the xhprof PHP module, profiling can be enabled / disabled from PHP code:
xhprof_enable();
doSlowOperation();
$profile_data = xhprof_disable();
The returned array will contain data about the number of calls, CPU time and memory usage of each
function that
XHProf has some (mostly undocumented) helper functions to display the data (see example), or you
can use other
You can use built-in functions to run PHP processes as forks. This is the most simple way to achieve
parallel work if
This allows you to put time intensive tasks (like uploading a file to another server or sending an email)
to another
thread so your script loads faster and can use multiple cores but be aware that this is not real
multithreading and
your main thread won't know what the children are up to.
Note that under Windows this will make another command prompt pop up for each fork you start.
master.php
pclose(popen($cmd,"r"));
else //for unix systems use shell exec with "&" in the end
worker.php
$sleeptime = $argv[1];
sleep($sleeptime);
PHP has built in function pcntl_fork for creating child process. pcntl_fork is same as fork in unix. It
does not take
in any parameters and returns integer which can be used to differentiate between parent and child
process.
<?php
$pid = pcntl_fork();
if ($pid == -1) {
} else if ($pid) {
// Parent process
} else {
// Child process
?>
As you can see -1 is an error in fork and the child was not created. On creation of child, we have two
processes
Another consideration here is a zombie process or defunct process when parent process finishes
before child
process. To prevent a zombie children process simply add pcntl_wait($status) at the end of parent
process.
pnctl_wait suspends execution of parent process until the child process has exited.
It is also worth noting that zombie process can't be killed using SIGKILL signal.
consider we need to write an PHP application that can run bash commands and print the output. We
will be using
proc_open , which will execute the command and return a resource that we can communicate with.
The following
code shows a basic implementation that runs pwd in bash from php
<?php
$descriptor = array(
);
if (is_resource($process)) {
fwrite($pipes[0], "pwd" . "\n");
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
?>
proc_open runs bash command with $descriptor as descriptor specifications. After that we use
is_resource to
validate the process. Once done we can start interacting with the child process using $pipes which is
generated
After that we can simply use fwrite to write to stdin of child process. In this case pwd followed by
carriage return.
Always remember to close the child process by using proc_close() which will terminate the child and
To start with multi-threading, you would need the pthreads-ext for php, which can be installed by
A simple example:
<?php
* @var string
*/
private $message;
$this->message = $message;
echo $this->message;
// Instantiate MyThread
// Start the thread. Also it is always a good practice to join the thread explicitly.
$myThread->start();
// and Thread::join() causes the context to wait for the thread to finish executing
$myThread->join();
Pooling provides a higher level abstraction of the Worker functionality, including the management of
<?php
private $workName;
/**
*/
$this->workName = $workName;
printf("A new work was submitted with the name: %s\n", $workName);
$workName = $this->workName;
// before the Work's are started (the block of code in the `run` method of your Work)
// by the Worker.
/* ... */
$pool->submit(new \AwesomeWork("DeadlyWork"));
$pool->submit(new \AwesomeWork("FatalWork"));
// See: http://stackoverflow.com/a/23600861/23602185
$pool->shutdown();
I have been searching on this topic for sometime till i found this post
function onLogin($user) {
storeTokenForUser($user, $token);
setcookie('rememberme', $cookie);
Then, to validate:
function rememberMe() {
if ($cookie) {
return false;
$usertoken = fetchTokenByUserName($user);
if (hash_equals($usertoken, $token)) {
logUserIn($user);
}
}
As the majority of websites run off PHP, application security is an important topic for PHP developers
to protect
their website, data, and clients. This topic covers best security practices in PHP as well as common
vulnerabilities
By default, PHP will tell the world what version of PHP you are using, e.g.
X-Powered-By: PHP/5.3.8
expose_php = off
header("X-Powered-By: Magic");
If either of the above methods do not work, there is also the header_remove() function that provides
you the ability
header_remove('X-Powered-By');
If attackers know that you are using PHP and the version of PHP that you are using, it's easier for them
to exploit
your server.
Problem
Cross-site scripting is the unintended execution of remote code by a web client. Any web application
might expose
itself to XSS if it takes input from a user and outputs it directly on a web page. If input includes HTML
or JavaScript,
remote code can be executed when this content is rendered by the web client.
// http://example.com/runme.js
document.write("I'm running");
<?php
<div><script src="http://example.com/runme.js"></script></div>
The 3rd party JavaScript will run and the user will see "I'm running" on the web page.
Solution
As a general rule, never trust input coming from a client. Every GET, POST, and cookie value could be
anything at all,
and should therefore be validated. When outputting any of these values, escape them so they will not
be evaluated
in an unexpected way.
Keep in mind that even in the simplest applications data can be moved around and it will be hard to
keep track of
Filter Functions
PHPs Filter Functions allow the input data to the php script to be sanitized or validated in many ways.
They are
HTML Encoding
htmlspecialchars will convert any "HTML special characters" into their HTML encodings, meaning they
will then not
be processed as standard HTML. To fix our previous example using this method:
<?php
// or
Would output:
<div><script src="http://example.com/runme.js"></script></div>
Everything inside the <div> tag will not be interpreted as a JavaScript tag by the browser, but instead
as a simple
<script src="http://example.com/runme.js"></script>
URL Encoding
When outputting a dynamically generated URL, PHP provides the urlencode function to safely output
valid URLs.
So, for example, if a user is able to input data that becomes part of another GET parameter:
<?php
$input = urlencode($_GET['input']);
// or
Sometimes you will want to send HTML or other kind of code inputs. You will need to maintain a list of
authorised
You can download standard lists available at the OWASP AntiSamy website. Each list is fit for a specific
kind of
There are libraries existing to filter HTML and prevent XSS attacks for the general case and performing
at least as
well as AntiSamy lists with very easy use. For example you have HTML Purifier
Problem
Cross-Site Request Forgery or CSRF can force an end user to unknowingly generate malicious requests
to a web
server. This attack vector can be exploited in both POST and GET requests. Let's say for example the url
endpoint
/delete.php?accnt=12 deletes account as passed from accnt parameter of a GET request. Now if an
authenticated
Solution
A common solution to this problem is the use of CSRF tokens. CSRF tokens are embedded into
requests so that a
web application can trust that a request came from an expected source as part of the application's
normal
workflow. First the user performs some action, such as viewing a form, that triggers the creation of a
unique token.
A sample form implementing this might look like
</form>
The token can then be validated by the server against the user session after form submission to
eliminate malicious
requests.
Sample code
...
<?php
session_start();
function generate_token() {
if(!isset($_SESSION["csrf_token"])) {
$token = random_bytes(64);
$_SESSION["csrf_token"] = $token;
} else {
$token = $_SESSION["csrf_token"];
return $token;
}
?>
<body>
</form>
</body>
...
...
<?php
session_start();
if ($_GET["csrf_token"] != $_SESSION["csrf_token"]) {
// Reset token
unset($_SESSION["csrf_token"]);
?>
...
There are many libraries and frameworks already available which have their own implementation of
CSRF
validation. Though this is the simple implementation of CSRF, You need to write some code to
regenerate your
CSRF token dynamically to prevent from CSRF token stealing and fixation.
Problem
In a similar way that SQL injection allows an attacker to execute arbitrary queries on a database,
command-line
injection allows someone to run untrusted system commands on a web server. With an improperly
secured server
Let's say, for example, a script allows a user to list directory contents on a web server.
<pre>
</pre>
(In a real-world application one would use PHP's built-in functions or objects to get path contents. This
example is for a
One would hope to get a path parameter similar to /tmp. But as any input is allowed, path could be ;
rm -fr /.
ls; rm -fr /
and attempt to delete all files from the root of the server.
Solution
All command arguments must be escaped using escapeshellarg() or escapeshellcmd(). This makes the
arguments non-executable. For each parameter, the input value should also be validated.
<pre>
Following the previous example with the attempt to remove files, the executed command becomes
And the string is simply passed as a parameter to ls, rather than terminating the ls command and
running rm.
It should be noted that the example above is now secure from command injection, but not from
directory traversal.
To fix this, it should be checked that the normalized path starts with the desired sub-directory.
PHP offers a variety of functions to execute system commands, including exec, passthru, proc_open,
shell_exec,
and system. All must have their inputs carefully validated and escaped.
strip_tags is a very powerful function if you know how to use it. As a method to prevent cross-site
scripting attacks
there are better methods, such as character encoding, but stripping tags is useful in some cases.
Basic Example
echo strip_tags($string);
Raw Output
Allowing Tags
Say you wanted to allow a certain tag but no other tags, then you'd specify that in the second
parameter of the
function. This parameter is optional. In my case I only want the <b> tag to be passed through.
Raw Output
<b>Hello, please remove the tags.</b>
Notice(s)
HTML comments and PHP tags are also stripped. This is hardcoded and can not be changed with
allowable_tags.
In PHP 5.3.4 and later, self-closing XHTML tags are ignored and only non-self-closing tags should be
used in
allowable_tags. For example, to allow both <br> and <br/>, you should use:
<?php
strip_tags($input, '<br>');
?>
Remote File Inclusion (also known as RFI) is a type of vulnerability that allows an attacker to include a
remote file.
<?php
include $_GET['page'];
/vulnerable.php?page=http://evil.example.com/webshell.txt?
Local File Inclusion (also known as LFI) is the process of including files on a server through the web
browser.
<?php
$page = 'pages/'.$_GET['page'];
if(isset($page)) {
include $page;
} else {
include 'index.php';
/vulnerable.php?page=../../../../etc/passwd
It is recommended to only allow including files you approved, and limit to those only.
<?php
$page = 'pages/'.$_GET['page'].'.php';
$allowed = ['pages/home.php','pages/error.php'];
if(in_array($page,$allowed)) {
include($page);
} else {
include('index.php');
By default PHP will output errors, warnings and notice messages directly on the page if something
unexpected in a
script occurs. This is useful for resolving specific issues with a script but at the same time it outputs
information you
Therefore it's good practice to avoid displaying those messages which will reveal information about
your server, like
your directory tree for example, in production environments. In a development or testing environment
these
A quick solution
You can turn them off so the messages don't show at all, however this makes debugging your script
harder.
GoalKicker.com – PHP Notes for Professionals 443
<?php
ini_set("display_errors", "0");
?>
display_errors = 0
Handling errors
A better option would be to store those error messages to a place they are more useful, like a
database:
try{
]);
} else {
});
This method will log the messages to the database and if that fails to a file instead of echoing it
directly into the
page. This way you can track what users are experiencing on your website and notify you immediately
if something
go's wrong.
If you want users to upload files to your server you need to do a couple of security checks before you
actually move
This array contains user submitted data and is not information about the file itself. While usually this
data is
generated by the browser one can easily make a post request to the same form using software.
$_FILES['file']['name'];
$_FILES['file']['type'];
$_FILES['file']['size'];
$_FILES['file']['tmp_name'];
type - Never use this data. It can be fetched by using PHP functions instead.
Normally the operating system does not allow specific characters in a file name, but by spoofing the
request you
can add them allowing for unexpected things to happen. For example, lets name the file:
../script.php%00.png
Take good look at that filename and you should notice a couple of things.
1. The first to notice is the ../, fully illegal in a file name and at the same time perfectly fine if you are
moving a
2. Now you might think you were verifying the file extensions properly in your script but this exploit
relies on
the url decoding, translating %00 to a null character, basically saying to the operating system, this
string ends
So now I've uploaded script.php to another directory, by-passing simple validations to file extensions.
It also bypasses .htaccess files disallowing scripts to be executed from within your upload directory.
You can use pathinfo() to extrapolate the name and extension in a safe manner but first we need to
replace
$illegal = array_merge(array_map('chr', range(0,31)), ["<", ">", ":", '"', "/", "\\", "|", "?",
$pathinfo = pathinfo($filename);
} else {
While now we have a filename and extension that can be used for storing, I still prefer storing that
information in a
database and give that file a generated name of for example, md5(uniqid().microtime())
+----+--------+-----------+------------+------+----------------------------------+----------------
-----+
+----+--------+-----------+------------+------+----------------------------------+----------------
-----+
00:38:54 |
+----+--------+-----------+------------+------+----------------------------------+----------------
-----+
This would resolve the issue of duplicate file names and unforseen exploits in the file name. It would
also cause the
attacker to guess where that file has been stored as he or she cannot specifically target it for
execution.
Mime-type validation
Checking a file extension to determine what file it is is not enough as a file may named image.png but
may very well
contain a php script. By checking the mime-type of the uploaded file against a file extension you can
verify if the file
You can even go 1 step further for validating images, and that is actually opening them:
if($img = imagecreatefromjpeg($filename)){
imagedestroy($img);
} else {
die('image failed to open, could be corrupt or the file contains something else.');
Most importantly, you should whitelist file extensions and mime types depending on each form.
is_array($allowed[$mime]) &&
in_array($extension, $allowed[$mime]);
$allowedFiletypes = [
];
PHP lacks a build-in function to encrypt and decrypt large files. openssl_encrypt can be used to
encrypt strings, but
So we have to write a userland function doing that. This example uses the symmetric AES-128-CBC
algorithm to
encrypt smaller chunks of a large file and writes them into another file.
Encrypt Files
/**
* Define the number of blocks that should be read from the source file for each chunk.
* So if we read 10,000 blocks we load 160kb into memory. You may adjust this value
*/
define('FILE_ENCRYPTION_BLOCKS', 10000);
/**
* Encrypt the passed file and saves the result in a new file with ".enc" as suffix.
* @param string $dest File name where the encryped file should be written to.
* @return string|false Returns the file name that has been created or FALSE if an error occurred
*/
$iv = openssl_random_pseudo_bytes(16);
$error = false;
while (!feof($fpIn)) {
$iv);
// Use the first 16 bytes of the ciphertext as the next initialization vector
fwrite($fpOut, $ciphertext);
fclose($fpIn);
} else {
$error = true;
fclose($fpOut);
} else {
$error = true;
Decrypt Files
To decrypt files that have been encrypted with the above function you can use this function.
/**
* Dencrypt the passed file and saves the result in a new file, removing the
* last 4 characters from file name.
* @param string $key The key used for the decryption (must be the same as for encryption)
* @param string $dest File name where the decryped file should be written to.
* @return string|false Returns the file name that has been created or FALSE if an error occurred
*/
$error = false;
while (!feof($fpIn)) {
$iv);
// Use the first 16 bytes of the ciphertext as the next initialization vector
fwrite($fpOut, $plaintext);
fclose($fpIn);
} else {
$error = true;
fclose($fpOut);
} else {
$error = true;
How to use
If you need a small snippet to see how this works or to test the above functions, look at the following
code.
$fileName = __DIR__.'/testfile.txt';
3. testfile.txt.dec with the decrypted file. This should have the same content as testfile.txt
This example illustrates the AES 256 symmetric cipher in CBC mode. An initialization vector is needed,
so we
generate one using an openssl function. The variable $strong is used to determine whether the IV
generated was
cryptographically strong.
Encryption
Decryption
/* Retrieve the IV from the database and the password from a POST request */
If the encrypted data needs to be sent or stored in printable text, then the base64_encode() and
base64_decode()
As more secure web services avoid storing passwords in plain text format, languages such as PHP
provide various
(undecryptable) hash functions to support the more secure industry standard. This topic provides
documentation
Create password hashes using password_hash() to use the current industry best-practice standard
hash or key
derivation. At time of writing, the standard is bcrypt, which means, that PASSWORD_DEFAULT contains
the same value
as PASSWORD_BCRYPT.
$options = [
];
The 'cost' value should be chosen based on your production server's hardware. Increasing it will make
the
password more costly to generate. The costlier it is to generate the longer it will take anyone trying to
crack it to
generate it also. The cost should ideally be as high as possible, but in practice it should be set so it
does not slow
down everything too much. Somewhere between 0.1 and 0.4 seconds would be okay. Use the default
value if you
are in doubt.
substitute those functions. Notice the compatibility pack requires PHP 5.3.7 or higher or a version that
has the $2y
If you are not able to use those, you can implement password hashing with crypt() As
password_hash() is
implemented as a wrapper around the crypt() function, you need not lose any functionality.
// with `password_hash()`
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
// on your system
if (CRYPT_BLOWFISH == 1) {
$salt = base64_encode($salt);
$source = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$dest = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
// `crypt()` determines which hashing algorithm to use by the form of the salt string
// that is passed in
Despite of reliability of crypt algorithm there is still vulnerability against rainbow tables. That's the
reason, why it's
A salt is something that is appended to the password before hashing to make source string unique.
Given two
identical passwords, the resulting hashes will be also unique, because their salts are unique.
A random salt is one of the most important pieces of your password security. This means that even
with a lookup
table of known password hashes an attacker can’t match up your user’s password hash with the
database
password hashes since a random salt has been used. You should use always random and
cryptographically secure
With password_hash() bcrypt algorithm, plain text salt is stored along with the resulting hash, which
means that
the hash can be transferred across different systems and platforms and still be matched against the
original
password.
Even when this is discouraged, you can use the salt option to define your own random salt.
$options = [
];
Important. If you omit this option, a random salt will be generated by password_hash() for each
password hashed.
Version ≥ 7.0
The salt option has been deprecated as of PHP 7.0.0. It is now preferred to simply use the salt that is
generated by
default.
If you are using the PASSWORD_DEFAULT method to let the system choose the best algorithm to hash
your passwords
with, as the default increases in strength you may wish to rehash old passwords as users log in
<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
// now determine if the existing hash was created with an algorithm that is
if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {
//$db->update(...);
?>
If the password_* functions are not available on your system (and you cannot use the compatibility
pack linked in
the remarks below), you can determine the algorithm and used to create the original hash in a method
similar to
the following:
<?php
if (substr($hashedPassword, 0, 4) == '$2y$' && strlen($hashedPassword) == 60) {
$cost = $matches[1];
?>
password_verify() is the built-in function provided (as of PHP 5.5) to verify the validity of a password
against a
known hash.
<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
else {
?>
All supported hashing algorithms store information identifying which hash was used in the hash itself,
so there is
no need to indicate which algorithm you are using to encode the plaintext password with.
If the password_* functions are not available on your system (and you cannot use the compatibility
pack linked in
the remarks below) you can implement password verification with the crypt() function. Please note
that specific
precautions must be taken to avoid timing attacks.
<?php
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
if (CRYPT_BLOWFISH == 1) {
// `crypt()` discards all characters beyond the salt length, so we can pass in
// in `password_hash()`
$status = 0;
if ($status === 0) {
else {
?>
Manual
The PHP Manual provides both a functional reference and a language reference along with
explanations of PHP's
major features. The PHP Manual, unlike most languages' documentation, encourages PHP developers
to add their
own examples and notes to each page of the documentation. This topic explains contribution to the
PHP manual,
PHP has great official documentation already at http://php.net/manual/. The PHP Manual documents
pretty much
all language features, the core libraries and most available extensions. There are plenty of examples to
learn from.
The PHP Documentation Team provides an online editor for the PHP Manual at https://edit.php.net. It
supports
multiple Single-Sign-On services, including logging in with your Stack Overflow account. You can find
an
Changes to the PHP Manual need to be approved by people from the PHP Documentation Team having
Doc Karma.
Doc Karma is somewhat like reputation, but harder to get. This peer review process makes sure only
factually
The PHP Manual is written in DocBook, which is an easy to learn markup language for authoring
books. It might
look a little bit complicated at first sight, but there are templates to get you started. You certainly don't
need to be a
Follow the manual's style guidelines. Ensure that the manual's style guidelines are always being
followed
Perform spelling and grammar checks. Ensure proper spelling and grammar is being used - otherwise
the
information presented may be more difficult to assimilate, and the content will look less professional.
Be terse in explanations. Avoid rambling to clearly and concisely present the information to
developers
Separate code from its output. This gives cleaner and less convoluted code examples for developers to
digest.
Check the page section order. Ensure that all sections of the manual page being edited are in the
correct
order. Uniformity in the manual makes it easier to quickly read and lookup information.
Remove PHP 4-related content. Specific mentions to PHP 4 are no longer relevant given how old it is
now.
Mentions of it should be removed from the manual to prevent convoluting it with unnecessary
information.
Properly version files. When creating new files in the documentation, ensure that the revision ID of
the file
Merge useful comments into the manual. Some comments contribute useful information that the
manual
could benefit from having. These should be merged into the main page's content.
Don't break the documentation build. Always ensure that the PHP manual builds properly before
PHP's source code is hosted on GitHub. To build from source you will first need to check out a working
copy of the
code.
mkdir /usr/local/src/php-7.0/
cd /usr/local/src/php-7.0/
If you want to add a feature, it's best to create your own branch.
./buildconf
./configure
make
make test
make install
If configuration fails due to missing dependencies, you will need to use your operating system's
package
management system to install them (e.g. yum, apt, etc.) or download and compile them from source.
on Windows
WampServer is a Windows web development environment. It allows you to create web applications
with Apache2,
PHP and a MySQL database. Alongside, PhpMyAdmin allows you to manage easily your databases.
WampServer is available for free (under GPML license) in two distinct versions : 32 and 64 bits.
Wampserver 2.5 is
not compatible with Windows XP, neither with SP3, nor Windows Server 2003. Older WampServer
versions are
available on SourceForge.
WampServer versions:
Providing currently:
Apache: 2.4.18
MySQL: 5.7.11
Installation is simple, just execute the installer, choose the location and finish it.
Once that is done, you may start WampServer. Then it starts in the system tray (taskbar), initially red
in color and
You may goto a browser and type localhost or 127.0.0.1 to get the index page of WAMP. You may work
on PHP
locally from now by storing the files in <PATH_TO_WAMP>/www/<php_or_html_file> and check the
result on
http://localhost/<php_or_html_file_name>
First of all you need to have IIS (Internet Information Services) installed and running on your machine;
IIS isn't
available by default, you have to add the characteristic from Control Panel -> Programs -> Windows
Characteristics.
1. Download the PHP version you like from http://windows.php.net/download/ and make sure you
download
Module: FastCgiModule
Executable: C:\PHP\php-cgi.exe
Name: PHP_FastCGI
https://www.microsoft.com/en-US/download/details.aspx?id=30679
Optionally you can install the PHP Manager for IIS which is of great help to setup the ini file and track
the log of
If you followed the installation guide now you are ready to test PHP.
Just like Linux, IIS has a directory structure on the server, the root of this tree is C:\inetpub\wwwroot\,
here is the
point of entry for all your public files and PHP scripts.
Now use your favorite editor, or just Windows Notepad, and type the following:
<?php
Save the file under C:\inetpub\wwwroot\index.php using the UTF-8 format (without BOM).
Then open your brand new website using your browser on this address: http://localhost/index.php
What is XAMPP?
XAMPP is the most popular PHP development environment. XAMPP is a completely free, open-source
and easy to
Download appropriate stable XAMPP version from their download page. Choose the download based
on the type of
OS (32 or 64bit and OS version) and the PHP version it has to support.
7zip: (For purists with low bandwidth: XAMPP as 7zip .7zip format archive)
1. Execute the XAMPP server installer by double clicking the downloaded .exe.
2. XAMPP is extracting to the subdirectory C:\xampp below the selected target directory.
3. Now start the file setup_xampp.bat, to adjust the XAMPP configuration to your system.
Note: If you choose a root directory C:\ as target, you must not start setup_xampp.bat.
Post-Install
Use the "XAMPP Control Panel" for additional tasks, like starting/stopping Apache, MySQL, FileZilla
and Mercury or
File handling
The installation is a straight forward process and once the installation is complete you may add
html/php files to be
hosted on the server in XAMPP-root/htdocs/. Then start the server and open http://localhost/file.php
on a
http://localhost/
http://127.0.0.1/
Environments
This will only install PHP. If you wish to serve a PHP file to the web you will also need to install a
webserver such as Apache, Nginx, or use PHP's built in web-server (php version 5.4+).
If you are in a Ubuntu version below 16.04 and want to use PHP 7 anyway, you can add Ondrej's PPA
php --version
You now have the capability to run PHP from the command line.
Use the yum command to manage packages in Enterprise Linux-based operating systems:
This installs a minimal install of PHP including some common features. If you need additional modules,
you will
need to install them separately. Once again, you can use yum to search for these packages:
Example output:
php-bcmath.x86_64 : A module for PHP applications for using the bcmath library
php-gd.x86_64 : A module for PHP applications for using the gd graphics library
Enterprise Linux distributions have always been conservative with updates, and typically do not
update beyond the
point release they shipped with. A number of third party repositories provide current versions of PHP:
IUS
Remi Colette
Webtatic
IUS and Webtatic provide replacement packages with different names (e.g. php56u or php56w to
install PHP 5.6)
while Remi's repository provides in-place upgrades by using the same names as the system packages.
Following are instructions on installing PHP 7.0 from Remi's repository. This is the simplest example, as
uninstalling
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
wget http://rpms.remirepo.net/enterprise/remi-release-6.rpm
Credits
Thank you greatly to all the people from Stack Overflow Documentation who helped provide this
content,
more changes can be sent to web@petercv.com for new content to be published or updated
54 69 6D Chapter 2
A.L Chapter 50
a4arpan Chapter 59
AeJey Chapter 18
afeique Chapter 2
Albzi Chapter 13
Aleks G Chapter 73
Alphonsus Chapter 41
AnotherGuy Chapter 29
AppleDash Chapter 2
Arun3x3 Chapter 14
Atiqur Chapter 15
bakahoe Chapter 17
bansi Chapter 65
Benjam Chapter 24
bhrached Chapter 37
Billy G Chapter 5
bish Chapter 64
bishop Chapter 79
blade Chapter 60
bnxio Chapter 29
Boysenb3rry Chapter 72
bpoiss Chapter 12
Bram Chapter 25
BSathvik Chapter 59
bwegs Chapter 5
bwoebi Chapters 2, 5, 6, 9, 11, 12, 15, 19, 31, 70, 92, 95, 96, 103 and 106
Calvin Chapter 10
Canis Chapter 26
caoglish Chapter 14
cFreed Chapter 9
Charlie H Chapter 5
chh Chapter 15
Christopher K. Chapter 9
cjsimon Chapter 55
Code4R7 Chapter 49
cpalinckx Chapter 5
CStff Chapter 19
cyberbit Chapter 30
CʸN Chapter 30
DanTheDJ1 Chapter 28
David Chapter 12
dikirill Chapter 33
Dipen Shah Chapter 9
DJ Sipe Chapter 41
Drew Chapter 58
Edward Chapter 35
Ekin Chapter 26
Emil Chapter 10
Epodax Chapter 39
Erki A Chapter 71
Ernestas Stankevi
F0G Chapter 2
Fathan Chapter 16
FeedTheWeb Chapter 31
Filip
Š Chapter 57
gabe3886 Chapter 43
Gaurav Chapter 1
GordonM Chapter 56
gracacs Chapter 9
GuRu Chapter 12
H. Pauwelyn Chapter 1
Hardik Kanjariya
ツ Chapter 43
Haridarshan Chapter 28
Harikrishnan Chapter 15
Hartman Chapter 33
hspaans Chapter 41
Ivan Chapter 58
ć Chapter 28
jasonlam604 Chapter 64
Jay Chapter 58
jayantS Chapter 18
JayIsTooCommon Chapter 10
JC Lee Chapter 32
jcalonso Chapter 12
jcuenod Chapter 19
Jdrupal Chapter 21
jesussegado Chapter 75
Jimmmy Chapter 33
jlapoutre Chapter 40
John C Chapter 29
JonasCz Chapter 1
juandemarco Chapter 15
K48 Chapter 5
Kamehameha Chapter 39
Katie Chapter 95
kero Chapter 26
kisanme Chapter 5
krtek Chapter 22
ksealey Chapter 13
Kuhan Chapter 81
Kzqai Chapter 1
leguano Chapter 89
Leith Chapter 31
Ligemer Chapter 31
Linus Chapter 35
littlethoughts Chapter 44
Loopo Chapter 33
MackieeE Chapter 12
maioman Chapter 64
Manikiran Chapter 20
Manolis Agkopian Chapter 58
Manulaiko Chapter 27
Marc Chapter 5
Mark H. Chapter 5
Martijn Chapter 59
Martin Chapter 9
martin Chapter 70
matiaslauriti Chapter 19
Matt S Chapters 1, 3, 10, 14, 16, 27, 41, 52, 58, 97, 101 and 103
Matze Chapter 47
Maxime Chapter 14
mickmackusa Chapter 28
Mike Chapter 68
miken32 Chapters 1, 5, 9, 10, 12, 19, 22, 31, 33, 38, 43, 50, 55, 56, 58, 66, 89, 105 and
107
mjsarfatti Chapter 39
moopet Chapter 9
mpavey Chapter 1
mTorres Chapter 29
Muhammad Chapter 1
Selim Chapter 41
mulquin Chapter 66
Mushti Chapter 2
n Chapter 29
Oldskool Chapter 36
Ormoz Chapter 74
Parziphal Chapter 2
paulmorriss Chapter 1
Paulpro Chapter 41
Pekka
웃 Chapter 64
philwc Chapter 58
Proger_Cbsk Chapter 12
p_blomberg Chapter 1
Quill Chapter 69
Raptor Chapter 12
RelicScoth Chapter 88
Rizier123 Chapter 12
robert Chapter 59
Ryan K Chapter 43
ryanm Chapter 5
ryanyuyu Chapter 31
S.I. Chapter 33
Safoor Safdar Chapter 41
scottevans93 Chapter 30
Script_Coded Chapter 10
Sebastianb Chapter 67
Shane Chapter 23
shyammakwana.me Chapter 53
signal Chapter 69
SirNarsh Chapter 83
SOFe Chapters 1, 2, 5, 10, 12, 13, 14, 15, 16, 21, 24, 25, 26, 28, 37, 39, 43, 44, 45, 57,
66, 74 and 84
Sumurai8 Chapter 41
Sunitrams' Chapter 99
SuperBear Chapter 10
Svish Chapter 5
talhasch Chapter 66
TecBrat Chapter 1
Technomad Chapter 32
TGrif Chapter 42
Thaillie Chapter 5
Thara Chapter 25
theomessin Chapter 45
Thijs Riezebeek Chapters 3, 12, 26, 27, 32, 40, 41, 42, 67 and 89
Thlbaut Chapter 12
Thomas Chapter 6
Timothy Chapter 5
Timur Chapter 5
toesslab.ch Chapter 1
Tom Chapters 81, 88 and 103
tpunt Chapters 5, 10, 12, 26, 35, 58, 104 and 105
tristansokol Chapter 60
TryHarder Chapter 19
Unex Chapter 2
user128216 Chapter 1
u_mulder Chapter 45
Veerendra Chapter 15
Ven Chapter 5
Victor T. Chapter 54
warlock Chapter 17
webNeat Chapter 66
wogsland Chapter 10
xims Chapter 1
Ziumin Chapter 43