Another PHP 8++ cheat sheet
Tags: php, php8
Published: 2022-02-22 18:07:32

## 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](https://www.php.net/manual/en/extensions.alphabetical.php) 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](https://github.com/nikic/php-ast).
 

### 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` or `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

<a href="https://www.zend.com/">The Zend Engine</a> (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](https://getcomposer.org/doc/) 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

Opening and ending tags:

```php
<?php
// my_script.php
?>
``` 

### Commenting code

```php
<?php
// 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:

```php
<?php
echo 'test';
?>
``` 

### Indentation is for readability only

Unlike Python, PHP does not care about indents and whitespaces.
 

### Simple quotes

```php
<?php
echo 'test';
?>
``` 

### Double quotes

Double quotes allows variable interpolation and the use of escaped chars:

```php
<?php
$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](https://www.php.net/manual/en/language.variables.superglobals.php)

## 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`


```php
<?php
for ($i = 0; $i < 23; $i++) {
    echo $i;
}
?>
```

### `foreach`

```php
<?php
$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:

```php
<?php
$j = 1;
while($j <= 5) {
  echo "$j \n";
  $j++;
}
?>
```

### `do while`

You use it when a test is dependant upon the results of the loop:

```php
<?php
$i = 0;
do {
    echo $i;
} while ($i > 0);
?>
```

## Operators

### Assignment

#### Assignment by value `=`


```php
<?php
$a = 110;
$a += 1;
$b = "Hello ";
$b .= "World";
?>
```

#### Assignment by reference `&`


```php
<?php
$a = 111;
$b = &$a; // $b and $a point to the same data, there's no copy
?>
```

### Arithmetic

#### `+`
Addition

#### `-`
Substraction

#### `*`
Multiplication

#### `/`
Division

#### `**`
Exponentiation

#### `%`
Modulo (reminder of a division)

### Logical

#### `AND`
And

#### `&&`
And

#### `OR`
Or

#### `||`
Or

#### `!`
Not

#### `xor`
`$a xor $b` means `$a` or `$b` but not both.

### Comparison

#### `===`
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

```php
<?php
$arr = [1, 2, 3];
$arr2 = [...$arr, 4, 5, 6];
?>
```

#### `_`


```php
<?php
$price = 1_1_1;
echo $price; // 111
?>
```

## Conditions

### Classic conditions

```php
<?php
if (CONDITION1) {
} elseif (CONDITION2) {
} else {
}
?>
```

### Switch case

```php
<?php
switch ($n) {
    case 1:
        $r = "You are alone";
        break;
    case 2:
        $r = "It's a double situation.";
        break;
    case 3:
        $r = "It's the third case.";
        break;
    default:
        $r = "I don't know.";
}
echo $r;
?>
```

###  Null Coalescing operator (@since PHP 7)

```php
<?php
$search = $_GET['search'] ?? 'does not exist or is null';
?>
```

### Match expression (@since PHP 8)

```php
<?php
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

```php
<?php
$a = (expression1) ? expression2 : expression3;
?>
```

### Elvis condition (or operator)

```php
<?php
$a = (expression1) ?: expression2; // I never use it, but it exists...
// the same as $a = (expression1) ? expression1 : expression2;
?>
```

## Scopes

global, local and static:

```php
<?php
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](https://www.php.net/manual/en/datetime.format.php) for the complete list.

## Filters

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:


```PHP
$email = "elon.musk@tesla.com";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // process
}
```
See [all filters](https://www.php.net/manual/en/filter.filters.php).

## Advanced PHP syntaxes

[Nowdoc](https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc) and [Heredoc](https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc) syntaxes allows handling multiple lines in a very convenient way.

### Heredoc

```php
<?php
echo <<<EOT
Hello, this is a test
Thank you for your time
EOT;
?>
``` 

### Nowdoc

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

## Working with arrays

{% embed https://dev.to/jmau111/things-you-probably-don-t-know-about-php-arrays-n0f %}

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

{% embed https://dev.to/jmau111/make-sense-of-generators-doa %}

## Getting started with files

### Reading a file as a string

```php
<?php
echo file_get_contents($file);
?>
```

### Writing in a file

```php
<?php
$file = 'file.txt';
$text = "Test write\n";
file_put_contents($file, $text, FILE_APPEND | LOCK_EX);
?>
``` 

### Deleting a file

`unlink($file);` 

### Working with CSV

<a href="https://www.php.net/manual/en/function.fgetcsv.php#refsect1-function.fgetcsv-examples">Source</a>:

```php
<?php
$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";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}
?>
``` 

## 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](https://www.php.net/manual/en/tutorial.forms.php)

## 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

```php
<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=db_username;charset=utf8mb4", "db_username", "db_password");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    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:

```php
<?php
$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);
$q->execute();
?>
```

[Source: PHP The Right Way - PDO](https://phptherightway.com/#pdo_extension)

## PHP CLI

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";
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"
```

```php
<?php
// 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](https://wiki.php.net/rfc/typed_properties_v2), 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](https://www.php.net/releases/8.0/en.php) for all details:

### Named Parameters

Allows for skipping optional parameters and much readable than positional arguments when using functions:

```php
<?php
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:

```php
<?php
return $user->getJob()?->getSalary()?->bitcoins;
?>
```

### Union Types

Allows using multiple types when casting parameters:

```php
<?php
function convert(int|float $value): int|float {}
?>
```

### Constructor property promotion

Allows for skipping LOTS of verbose initializations in PHP classes when passing arguments:

```php
<?php
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

### `str_contains()`


```php
<?php
if (str_contains($string, 'target')) {
    // code
}
?>
```

## New in PHP 8.1

Here are cool new features I like, see [release announcement](https://www.php.net/releases/8.1/en.php) for all details:

### Enumerations

An <a href="https://wiki.php.net/rfc/enumerations">Enum</a> is a special kind of object that consists of a custom type that is limited to one or a discrete number of possible values:

```php
<?php
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, 8):

```php
<?php
$arr1 = ['a' => 1];
$arr2 = ['b' => 2];
$results = ['a' => 0, ...$arr1, ...$arr2];
print_r($results);
?>
```

### Never return type

The <a href="https://wiki.php.net/rfc/noreturn_type">Never return type</a> allows for specifying that the functions won't return any value and will likely die or exit:

```php
<?php
function redirect_uri(string $uri): never {
    header('Location: ' . $uri);
    exit();
}
?>
```

### Pure Intersection Types (`&`)

<a href="https://wiki.php.net/rfc/pure-intersection-types">Pure Intersection Types</a> are a great way to force multiple constraints:

```php
<?php
function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;
    }
    count($value);
}
?>
```

## Catching errors in PHP 8

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


```PHP
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.

## Misc

### Destructuring

```php
<?php
$array = ['first', 'second', 'third',];
[, , $c] = $array;
// $c = 'third'
?>
```

### Arrow functions

```php
<?php
$y = 111;
$f = fn($x) => $x + $y;
echo $f(222);// 333
?>
```

### Throw expressions

```php
<?php
$err = fn () => throw new CustomErrors();
?>
```

### `::class`

Lovely:

```php
<?php
$my_class = new MyClass();
var_dump($my_class::class);// instead of using get_class()
?>
```

### Trailing comma in function or class definition

```php
<?php
public static function(
    string $name,
    int $number,
) {
    // code
}
?>
```

## PSR

[PSR](https://www.php-fig.org/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.

## OOP

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](https://phptherightway.com/pages/Design-Patterns.html)

## Caching

### My favorite caching solutions for PHP

*   [Illuminate](https://github.com/php-cache/illuminate-adapter)
*   [Opcache](https://www.php.net/manual/en/book.opcache.php)
*   [Redis PHP](https://developer.redis.com/develop/php/)

## Debugging and profiling

### <a href="https://www.php.net/manual/en/debugger.php#118058">console.log</a> PHP data

```php
<?php
function console_log( $data ){
  echo '<script>';
  echo 'console.log('. json_encode( $data ) .')';
  echo '</script>';
}
?>
```

### xdebug

<a href="https://xdebug.org/">xdebug</a>

### Helpers

* `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:

* [xhprof](https://www.php.net/manual/en/book.xhprof.php)
* [Blackfire](https://www.blackfire.io/php)

### Tests, tests, and tests

Professionals run unit, integration, acceptance tests, and many other variants to prevent nasty regressions: [PHPunit](https://phpunit.readthedocs.io/en/9.5/)

## Handling HTTP requests

There are many ways but I prefer using the [http-client package](https://github.com/symfony/http-client): `composer require symfony/http-client`.

This low-level HTTP client with support for both PHP stream wrappers and [cURL](https://www.php.net/manual/en/book.curl.php). You can fetch data synchronously OR asynchronously.

See [http-client cheat sheet](https://assets.andreiabohner.org/symfony/sf43-httpclient-cheat-sheet.pdf).