This website has been archived

My PHP 8++ cheat sheet

Important PHP Concepts to know

PHP (Hypertext Preprocessor) is a powerful C-like scripting language that sometimes suffers from a bad reputation due to its legacy. While most constructive critics have some points with PHP 4 or 5, PHP 7 and PHP 8 are a new done.

The language has now strong types, syntactic sugars and many other features you will love, especially if you come from other programming languages.

PHP is an interpreted language Unlike some languages, PHP is not self-contained. Your code will need in addition a third-party webserver (e.g., Apache, Nginx), a compiler and the PHP interpreter to work.
The interpreter reads your .php file, parses it, executes it, and then send the output to the webserver. Then, the server sends the output in the HTTP response to the browser (the client).
PHP extensions and reusable functions PHP works with extensions mostly written in C but some are third party libraries simply written in PHP. Some compile with the PHP binary and some are optional and must be included in the php.ini file where you write directives for PHP.
Lifecycle: Lexing Most of your php code turns into a sequence of tokens (tokenizing), but special symbols such as ?, =, or ; are already tokenized. The lexer generates lexemes which are a mix of numbers and letters representing the tokens and matching values.
Lifecycle: Parsing / AST The parser takes the streams of tokens generated with the lexer as input. It applies grammar rules to validate these tokens and generates an abstract tree (AST) using the php-ast extension.
Lifecycle: Compilation / opcodes Compilation is the act of consuming the AST. It generates opcodes by traversing the AST and run a few internal optimizations.
These opcodes are not unreadable but it's significantly different from the original source code with, for example, the results of intermediary operations such as true/false for a condition like $a === $b.
Lifecycle: Opcache Opcache can be enabled to cache opcodes, saving the results of previous operations and optimizing instructions to improve performances.
Lifecycle: Interpretation The Zend Engine (VM) takes opcodes as input to output the results and execute instructions.
Lifecycle: PHP 8 JIT compilation / opcache The Just-In-Time compilation works with Opcache (that stores precompiled sequences in memory to bypass parsing and interpretation) and improves the performances of CPU-intensive applications (e.g. Machine Learning, complexe mathematical operations, 3D, etc). JIT must be fine-tuned and does not fit all projects.
Composer Composer is the package manager for PHP. It's a smart way to handle and load dependencies.

Data types in PHP 8

Integers Numbers such as 1, 2, 3, 4, 5, 6, ..., n
Booleans true or false
Strings Sequences of chars such as "Pink Elephants"
Doubles Floats such as 38.2
Arrays Collections of values such as ["a","b","c",]
Objects Instances of PHP classes that can carry lots of functions and values.
Resources Special references to external resources like remote connections (e.g., databases, cloud services).
NULL Special type with a unique value of NULL.
Mixed Anything!
Iterable Array or traver­sable

Common Escape Characters

\n Line
\t Horizontal tabulation
\v Vertical tabulation
\r Carriage return
\e Escape

Basic PHP Syntax

Always use canonical tags All .php files must have opening and ending tags:
// my_script.php
Commenting code
// a comment using "//", you can also use "#"
Handle multiple lines 
with '/' 
and '*'
PHP is case sensitive $lower is not the same variable as $Lower.
Never omit the semi-colon Unlike with CSS or JavaScript, you cannot skip the ; at the end of expressions and statements:
echo 'test';
Indentation is for readability only Unlike Python, PHP does not care about indents and whitespaces.
Simple quotes
echo 'test';
Double quotes Double quotes allows variable interpolation and the use of escaped chars:
$my_var = 'test';
echo "\t\t\t This is a $my_var \n";

Predefined variables

Also known as superglobals, predefined variables are useful to handle specific treatments:

$GLOBALS References all variables available in global scope.
$_REQUEST Associative array of variables passed to $_GET, $_POST and $_COOKIE.
$_POST Associative array of variables passed to the current script mostly with forms (application/x-www-form-urlencoded or multipart/form-data HTTP Content-Type)
$_COOKIE Associative array of variables passed to the current script via HTTP Cookies.
$_GET Associative array of variables passed to the current script via the URL parameters.
$_SERVER Server and execution environment information.

Find more superglobals here

Magic constants

__DIR__ Directory of the current file.
__FILE__ Full path of the current file.
__LINE__ Number of the current line in the file.
__CLASS__ Name of the current class, including its namespace.
__FUNCTION__ Name of the current function.
__METHOD__ Name of the current method.
__NAMESPACE__ Name of the current namespace.
__TRAIT__ Name of the current trait.

Loop, loop, loop

for ($i = 0; $i < 23; $i++) {
    echo $i;
$letters = ["a", "b", "c",]
foreach ($letters as $letter) {
    echo "$letter \n";
while Be careful, if the condition is malformed, you may end up with an infinite loop:
$j = 1;

while($j <= 5) {
  echo "$j \n";
do while It just checks the truth expression at the end of each iteration instead of in the beginning. You use it when a test is dependant upon the results of the loop:
$i = 0;
do {
    echo $i;
} while ($i > 0);



Assignment by value =
$a = 110;
$a += 1;
$b = "Hello ";
$b .= "World";
Assignment by reference &
$a = 111;
$b = &$a; // $b and $a point to the same data, there's no copy


+ Addition
- Substraction
* Multiplication
/ Division
** Exponentiation
% Modulo (reminder of a division)


&& And
|| Or
! Not
xor $a xor $b means $a or $b but not both.


=== Identical
!== Not identical
<> Not equal
< Lower than
> Greater than
<= Lower than or equal to
>= Equal to or greater than
<=> Lower than, equal to, or greater than

Unusual or lesser known

| or, but inclusive
^ xor
~ not
... Spread operator to merge elements
$arr = [1, 2, 3];
$arr2 = [...$arr, 4, 5, 6];
$price = 1_1_1;
echo $price; // 111


Classic conditions

} elseif (CONDITION2) {

} else {

Switch case
switch ($n) {
    case 1:
        $r = "You are alone";
    case 2:
        $r = "It's a double situation.";
    case 3:
        $r = "It's the third case.";
        $r = "I don't know.";
echo $r;
Null Coalescing operator (@since PHP 7)
$search = $_GET['search'] ?? 'does not exist or is null';
Match expression (@since PHP 8)
echo match ($n) {
  1 => "You are alone",
  2 => "It's a double situation.",
  3 => "It's the third case.",
  default => "I don't know.",
Ternary condition
$a = (expression1) ? expression2 : expression3;
Elvis condition (or operator)
$a = (expression1) ?: expression2; // I never use it, but it exists...
// the same as $a = (expression1) ? expression1 : expression2;


3 scopes global, local and static:
function test() {
    $b = "b"; // local
    global $c;
    $c = "c"; // global
    static $d = 0;
    $d++;// $d increment on each function call

Date and time formats

D Days Mon to Sun
d Days 01 to 31
j Days 1 to 31
L Leap year or not (1 or 0)
l Days Sunday to Saturday
N Days 1 (Mon) to 7 (Sat)
w Days 0 (Sun) to 6 (Sat)
M Months Jan to Dec
m Months 01 to 12
n Months 1 to 12
F Months January to December
Y Year four digits (e.g., 2022)
y Year two digits (e.g., 22)
A AM and PM
a am and pm
G Hours 0 to 23
g Hours 1 to 12
H Hours 00 to 23
h Hours 01 to 12
i Minutes 00 to 59
s Seconds 00 to 59

See documentation for the complete list.


Filters flags and constants are particularly helpful to validate or sanitize inputs. For example, instead of using far-fetched regex to filter emails, you can do:

$email = "";

if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // process

See all filters.

Advanced PHP syntaxes

Nowdoc and Heredoc syntaxes allows handling multiple lines in a very convenient way.

echo <<<EOT
Hello, this is a test
Thank you for your time
$my_var = 'test';
echo <<<EOT
Hello, this is a $my_var
Thank you for your time

Working with arrays

Maybe start with this guide. Arrays are not specific to PHP, but a PHP developer uses them all the time.

You cannot skip it if you want to learn the language.

Working with Generators

Make sense of generators

Getting started with files

Reading a file as a string
echo file_get_contents($file);
Writing in a file
$file = 'file.txt';
$text = "Test write\n";
file_put_contents($file, $text, FILE_APPEND | LOCK_EX);
Deleting a file unlink($file);
Working with CSV Source:
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";

Getting started with forms

Forms are probably the most targeted elements by hackers, especially on PHP-based websites, as they’re often connected to other instances such as a SQL database.

Websites behind paywalls with various forms are primary targets.

In PHP, data often changes according to URLs (GET requests) or HTTP POST requests. For example, a search form will likely work with URL parameters, whereas a login form will send a POST request.

As a result, form processing may involve super globals $_GET and $_POST to catch input values.

See this guide

Getting started with databases

You will likely use a database along with PHP. Regardless of the database management system, you need to use the right PHP tools to connect and interact with the database from your PHP script.

Otherwise, your application might be prone to SQL injections.

Getting started with PDO
try {
    $pdo = new PDO("mysql:host=localhost;dbname=db_username;charset=utf8mb4", "db_username", "db_password");
    if ($pdo) {
	    $statement = $pdo->query("SELECT some_field FROM some_table");
        $row = $statement->fetch(PDO::FETCH_ASSOC);
        echo htmlentities($row['some_field']);
} catch(\PDOException $e) {
   throw new \PDOException($e->getMessage(), (int)$e->getCode());
Securing inputs with PDO PDO is pretty handy to escape and sanitize inputs:
$q = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);
$q->bindParam(':id', $id, PDO::PARAM_INT);

Source: PHP The Right Way - PDO


You can run PHP from the terminal in various ways:

Executing .php files
php my_script.php
Starting an interactive shell
php -a
Interactive shell

php > echo "hi";
php > 
Passing instructions as arguments
php -r 'echo "hi";'

You can write PHP scripts that are meant to be used from the terminal:

Passing arguments to PHP scripts
php my_script.php "test"
// my_script.php
print_r($argv[1]);// test
Start a local server php -S localhost:1001

New in PHP 8

To be fair, PHP 7.4 initiated major evolutions such as typed properties, but PHP 8 puts PHP to the next level.

Be careful if you have to migrate from a previous version, though, as it’s much much stricter than before. PHP 8 throws way more fatal errors on purpose to be less permissive. The silence operator @ no longer exists and the default error_reporting level is E_ALL!

Here are cool new features I like, see release announcement for all details:

Named Parameters Allows for skipping optional parameters and much readable than positional arguments when using functions:
function say_hello(string $message = 'Hi', string $name) {
    echo "$message $name";
say_hello(name: "Zed");
Null-safe Operator Allows for removing LOTS of unnecessary verbose if/else conditions:
return $user->getJob()?->getSalary()?->bitcoins;
Union Types Allows using multiple types when casting parameters:
function convert(int|float $value): int|float {}
Constructor property promotion Allows for skipping LOTS of verbose initializations in PHP classes when passing arguments:
class Character {
    public function __construct(private string $name) {}
0 == 'ki' // false This condition returns true before PHP 8, which is permissive.
The JIT compiler See the first section: Important PHP Concepts
if (str_contains($string, 'target')) {
    // code

New in PHP 8.1

Here are cool new features I like, see release announcement for all details:

Enumerations An Enum is a special kind of object that consists of a custom type that is limited to one or a discrete number of possible values:
enum Colors
    case Red;
    case Blue;
    case Green;
Array unpacking support for string-keyed arrays You can use the spread operator with string-keyed arrays (only num-keyed arrays in PHP 7 and 8):
$arr1 = ['a' => 1];
$arr2 = ['b' => 2];
$results = ['a' => 0, ...$arr1, ...$arr2];
Never return type The Never return type allows for specifying that the functions won't return any value and will likely die or exit:
function redirect_uri(string $uri): never {
    header('Location: ' . $uri);
Pure Intersection Types (&) Pure Intersection Types are a great way to force multiple constraints:
function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;


Catching errors in PHP 8

In PHP 8, you don’t have to capture the exception, for example:

class CustomException extends \Exception {}

try {
    // code
 } catch (CustomException) { // instead of catch (CustomException $exception)
    Log::error("Error");// Log is a custom class too (not native)

It should be noted that PHP now throw exceptions frequently:

Most of the internal functions now throw an Error exception if the validation of the parameters fails.


$array = ['first', 'second', 'third',];
[, , $c] = $array;
// $c = 'third'
Arrow functions
$y = 111;
$f = fn($x) => $x + $y;
echo $f(222);// 333
Throw expressions
$err = fn () => throw new CustomErrors();
::class Lovely:
$my_class = new MyClass();
var_dump($my_class::class);// instead of using get_class()
Trailing comma in function or class definition
public static function(
    string $name,
    int $number,
) {
    // code


PSR are standards for writing PHP code. You might have already seen PSR-0 or PSR-4, especially when autoloading dependencies through Composer. These are specific versions of PHP standards.


Object-oriented programming is fun and powerful, but hard to master. The good news is that you find it in most programming languages, so learning it is a pretty good investment.

Some developers think it’s the only proper way to develop software, some stick with procedural code. In any case, you can’t skip it.

Learn Design Patterns


My favorite caching solutions for PHP

Debugging and profiling

console.log PHP data
function console_log( $data ){
  echo '<script>';
  echo 'console.log('. json_encode( $data ) .')';
  echo '</script>';
xdebug xdebug
  • print_r(): accepts one parameter
  • var_dump(): accepts multiple parameters
  • var_dump(debug_backtrace()): generates a backtrace
  • debug_print_backtrace(): prints a backtrace
Profilers Applications may require profiling tools to prevent memory leaks and other performances issues:
Tests, tests, and tests Professionals run unit, integration, acceptance tests, and many other variants to prevent nasty regressions:

Handling HTTP requests

There are many ways but I prefer using the http-client package: composer require symfony/http-client.

This low-level HTTP client with support for both PHP stream wrappers and cURL. You can fetch data synchronously OR asynchronously.

See http-client cheat sheet.