Files
molenda.net/eeeeee/php_code.txt
T
Sebastian Molenda ab96d82fcf init
2026-05-12 21:10:38 +02:00

4252 lines
82 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- Source: boolean.xml ---
<?php
$foo = True; // assign the value TRUE to $foo
?>
--- Source: boolean.xml ---
<?php
$action = "show_version";
$show_separators = true;
// == is an operator which tests
// equality and returns a boolean
if ($action == "show_version") {
echo "The version is 1.23";
}
// this is not necessary...
if ($show_separators == TRUE) {
echo "<hr>\n";
}
// ...because this can be used with exactly the same meaning:
if ($show_separators) {
echo "<hr>\n";
}
?>
--- Source: boolean.xml ---
<?php
var_dump((bool) ""); // bool(false)
var_dump((bool) "0"); // bool(false)
var_dump((bool) 1); // bool(true)
var_dump((bool) -2); // bool(true)
var_dump((bool) "foo"); // bool(true)
var_dump((bool) 2.3e5); // bool(true)
var_dump((bool) array(12)); // bool(true)
var_dump((bool) array()); // bool(false)
var_dump((bool) "false"); // bool(true)
?>
--- Source: integer.xml ---
<?php
$a = 1234; // decimal number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0o123; // octal number (as of PHP 8.1.0)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
$a = 0b11111111; // binary number (equivalent to 255 decimal)
$a = 1_234_567; // decimal number (as of PHP 7.4.0)
?>
--- Source: integer.xml ---
decimal : [1-9][0-9]*(_[0-9]+)*
| 0
hexadecimal : 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*
octal : 0[oO]?[0-7]+(_[0-7]+)*
binary : 0[bB][01]+(_[01]+)*
integer : decimal
| hexadecimal
| octal
| binary
--- Source: integer.xml ---
<?php
$large_number = 50000000000000000000;
var_dump($large_number); // float(5.0E+19)
var_dump(PHP_INT_MAX + 1); // 32-bit system: float(2147483648)
// 64-bit system: float(9.2233720368548E+18)
?>
--- Source: integer.xml ---
<?php
var_dump(25/7); // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7)); // float(4)
?>
--- Source: integer.xml ---
<?php
function foo($value): int {
return $value;
}
var_dump(foo(8.1)); // "Deprecated: Implicit conversion from float 8.1 to int loses precision" as of PHP 8.1.0
var_dump(foo(8.1)); // 8 prior to PHP 8.1.0
var_dump(foo(8.0)); // 8 in both cases
var_dump((int) 8.1); // 8 in both cases
var_dump(intval(8.1)); // 8 in both cases
?>
--- Source: integer.xml ---
<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>
--- Source: callable.xml ---
<?php
function foo(callable $callback) {
$callback();
}
?>
--- Source: callable.xml ---
<?php
// Using anonymous function syntax
$double1 = function ($a) {
return $a * 2;
};
// Using first-class callable syntax
function double_function($a) {
return $a * 2;
}
$double2 = double_function(...);
// Using arrow function syntax
$double3 = fn($a) => $a * 2;
// Using Closure::fromCallable
$double4 = Closure::fromCallable('double_function');
// Use the closure as a callback here to
// double the size of each element in our range
$new_numbers = array_map($double1, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double2, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double3, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double4, range(1, 5));
print implode(' ', $new_numbers);
?>
--- Source: callable.xml ---
<?php
// An example callback function
function my_callback_function() {
echo 'hello world!', PHP_EOL;
}
// An example callback method
class MyClass {
static function myCallbackMethod() {
echo 'Hello World!', PHP_EOL;
}
}
// Type 1: Simple callback
call_user_func('my_callback_function');
// Type 2: Static class method call
call_user_func(['MyClass', 'myCallbackMethod']);
// Type 3: Object method call
$obj = new MyClass();
call_user_func([$obj, 'myCallbackMethod']);
// Type 4: Static class method call
call_user_func('MyClass::myCallbackMethod');
// Type 5: Static class method call using ::class keyword
call_user_func([MyClass::class, 'myCallbackMethod']);
// Type 6: Relative static class method call
class A {
public static function who() {
echo 'A', PHP_EOL;
}
}
class B extends A {
public static function who() {
echo 'B', PHP_EOL;
}
}
call_user_func(['B', 'parent::who']); // deprecated as of PHP 8.2.0
// Type 7: Objects implementing __invoke can be used as callables
class C {
public function __invoke($name) {
echo 'Hello ', $name;
}
}
$c = new C();
call_user_func($c, 'PHP!');
?>
--- Source: float.xml ---
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // as of PHP 7.4.0
?>
--- Source: float.xml ---
LNUM [0-9]+(_[0-9]+)*
DNUM ({LNUM}?"."{LNUM}) | ({LNUM}"."{LNUM}?)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
--- Source: float.xml ---
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
if (abs($a - $b) < $epsilon) {
echo "true";
}
?>
--- Source: enumerations.xml ---
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
function do_stuff(Suit $s)
{
// ...
}
do_stuff(Suit::Spades);
?>
--- Source: array.xml ---
<?php
$array1 = array(
"foo" => "bar",
"bar" => "foo",
);
// Using the short array syntax
$array2 = [
"foo" => "bar",
"bar" => "foo",
];
var_dump($array1, $array2);
?>
--- Source: array.xml ---
<?php
$array = array(
1 => "a",
"1" => "b",
1.5 => "c",
true => "d",
);
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = array("foo", "bar", "hello", "world");
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = array(
"a",
"b",
6 => "c",
"d",
);
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = array(
1 => 'a',
'1' => 'b', // the value "a" will be overwritten by "b"
1.5 => 'c', // the value "b" will be overwritten by "c"
-1 => 'd',
'01' => 'e', // as this is not an integer string it will NOT override the key for 1
'1.5' => 'f', // as this is not an integer string it will NOT override the key for 1
true => 'g', // the value "c" will be overwritten by "g"
false => 'h',
'' => 'i',
null => 'j', // the value "i" will be overwritten by "j"
'k', // value "k" is assigned the key 2. This is because the largest integer key before that was 1
2 => 'l', // the value "k" will be overwritten by "l"
);
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = [];
$array[-5] = 1;
$array[] = 2;
var_dump($array);
?>
--- Source: array.xml ---
<?php
$array = array(
"foo" => "bar",
42 => 24,
"multi" => array(
"dimensional" => array(
"array" => "foo"
)
)
);
var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
?>
--- Source: array.xml ---
<?php
function getArray() {
return array(1, 2, 3);
}
$secondElement = getArray()[1];
var_dump($secondElement);
?>
--- Source: array.xml ---
<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; // This is the same as $arr[13] = 56;
// at this point of the script
$arr["x"] = 42; // This adds a new element to
// the array with key "x"
unset($arr[5]); // This removes the element from the array
var_dump($arr);
unset($arr); // This deletes the whole array
var_dump($arr);
?>
--- Source: array.xml ---
<?php
// Create a simple array.
$array = array(1, 2, 3, 4, 5);
print_r($array);
// Now delete every item, but leave the array itself intact:
foreach ($array as $i => $value) {
unset($array[$i]);
}
print_r($array);
// Append an item (note that the new key is 5, instead of 0).
$array[] = 6;
print_r($array);
// Re-index:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>
--- Source: array.xml ---
<?php
$source_array = ['foo', 'bar', 'baz'];
[$foo, $bar, $baz] = $source_array;
echo $foo, PHP_EOL; // prints "foo"
echo $bar, PHP_EOL; // prints "bar"
echo $baz, PHP_EOL; // prints "baz"
?>
--- Source: array.xml ---
<?php
$source_array = [
[1, 'John'],
[2, 'Jane'],
];
foreach ($source_array as [$id, $name]) {
echo "{$id}: '{$name}'\n";
}
?>
--- Source: array.xml ---
<?php
$source_array = ['foo', 'bar', 'baz'];
// Assign the element at index 2 to the variable $baz
[, , $baz] = $source_array;
echo $baz; // prints "baz"
?>
--- Source: array.xml ---
<?php
$source_array = ['foo' => 1, 'bar' => 2, 'baz' => 3];
// Assign the element at index 'baz' to the variable $three
['baz' => $three] = $source_array;
echo $three, PHP_EOL; // prints 3
$source_array = ['foo', 'bar', 'baz'];
// Assign the element at index 2 to the variable $baz
[2 => $baz] = $source_array;
echo $baz, PHP_EOL; // prints "baz"
?>
--- Source: array.xml ---
<?php
$a = 1;
$b = 2;
[$b, $a] = [$a, $b];
echo $a, PHP_EOL; // prints 2
echo $b, PHP_EOL; // prints 1
?>
--- Source: array.xml ---
<?php
$a = array(1 => 'one', 2 => 'two', 3 => 'three');
/* will produce an array that would have been defined as
$a = array(1 => 'one', 3 => 'three');
and NOT
$a = array(1 => 'one', 2 =>'three');
*/
unset($a[2]);
var_dump($a);
$b = array_values($a);
// Now $b is array(0 => 'one', 1 =>'three')
var_dump($b);
?>
--- Source: array.xml ---
<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>
--- Source: array.xml ---
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Simple array:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
echo "\nChecking $i: \n";
echo "Bad: " . $array['$i'] . "\n";
echo "Good: " . $array[$i] . "\n";
echo "Bad: {$array['$i']}\n";
echo "Good: {$array[$i]}\n";
}
?>
--- Source: array.xml ---
<?php
// Show all errors
error_reporting(E_ALL);
$arr = array('fruit' => 'apple', 'veggie' => 'carrot');
// Correct
echo $arr['fruit'], PHP_EOL; // apple
echo $arr['veggie'], PHP_EOL; // carrot
// Incorrect. This does not work and throws a PHP Error because
// of an undefined constant named fruit
//
// Error: Undefined constant "fruit"
try {
echo $arr[fruit];
} catch (Error $e) {
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
}
// This defines a constant to demonstrate what's going on. The value 'veggie'
// is assigned to a constant named fruit.
define('fruit', 'veggie');
// Notice the difference now
echo $arr['fruit'], PHP_EOL; // apple
echo $arr[fruit], PHP_EOL; // carrot
// The following is okay, as it's inside a string. Constants are not looked for
// within strings, so no error occurs here
echo "Hello $arr[fruit]", PHP_EOL; // Hello apple
// With one exception: braces surrounding arrays within strings allows constants
// to be interpreted
echo "Hello {$arr[fruit]}", PHP_EOL; // Hello carrot
echo "Hello {$arr['fruit']}", PHP_EOL; // Hello apple
// Concatenation is another option
echo "Hello " . $arr['fruit'], PHP_EOL; // Hello apple
?>
--- Source: array.xml ---
<?php
// This will not work, and will result in a parse error, such as:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// This of course applies to using superglobals in strings as well
print "Hello $arr['fruit']";
print "Hello $_GET['foo']";
?>
--- Source: array.xml ---
<?php
echo $arr[somefunc($bar)];
?>
--- Source: array.xml ---
<?php
$error_descriptions[E_ERROR] = "A fatal error has occurred";
$error_descriptions[E_WARNING] = "PHP issued a warning";
$error_descriptions[E_NOTICE] = "This is just an informal notice";
?>
--- Source: array.xml ---
<?php
$error_descriptions[1] = "A fatal error has occurred";
$error_descriptions[2] = "PHP issued a warning";
$error_descriptions[8] = "This is just an informal notice";
?>
--- Source: array.xml ---
<?php
class A {
private $B;
protected $C;
public $D;
function __construct()
{
$this->{1} = null;
}
}
var_export((array) new A());
?>
--- Source: array.xml ---
<?php
class A {
private $A; // This will become '\0A\0A'
}
class B extends A {
private $A; // This will become '\0B\0A'
public $AA; // This will become 'AA'
}
var_dump((array) new B());
?>
--- Source: array.xml ---
<?php
// Using short array syntax.
// Also, works with array() syntax.
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; // [1, 2, 3]
$arr3 = [0, ...$arr1]; // [0, 1, 2, 3]
$arr4 = [...$arr1, ...$arr2, 111]; // [1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; // [1, 2, 3, 1, 2, 3]
function getArr() {
return ['a', 'b'];
}
$arr6 = [...getArr(), 'c' => 'd']; // ['a', 'b', 'c' => 'd']
var_dump($arr1, $arr2, $arr3, $arr4, $arr5, $arr6);
?>
--- Source: array.xml ---
<?php
// string key
$arr1 = ["a" => 1];
$arr2 = ["a" => 2];
$arr3 = ["a" => 0, ...$arr1, ...$arr2];
var_dump($arr3); // ["a" => 2]
// integer key
$arr4 = [1, 2, 3];
$arr5 = [4, 5, 6];
$arr6 = [...$arr4, ...$arr5];
var_dump($arr6); // [1, 2, 3, 4, 5, 6]
// Which is [0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6]
// where the original integer keys have not been retained.
?>
--- Source: array.xml ---
<?php
$arr1 = [1, 2, 3];
$arr2 = ['a' => 4];
$arr3 = [...$arr1, ...$arr2];
// Fatal error: Uncaught Error: Cannot unpack array with string keys in example.php:5
$arr4 = [1, 2, 3];
$arr5 = [4, 5];
$arr6 = [...$arr4, ...$arr5]; // works. [1, 2, 3, 4, 5]
?>
--- Source: array.xml ---
<?php
// This:
$a = array( 'color' => 'red',
'taste' => 'sweet',
'shape' => 'round',
'name' => 'apple',
4 // key will be 0
);
$b = array('a', 'b', 'c');
var_dump($a, $b);
// . . .is completely equivalent with this:
$a = array();
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name'] = 'apple';
$a[] = 4; // key will be 0
$b = array();
$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// After the above code is executed, $a will be the array
// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round',
// 'name' => 'apple', 0 => 4), and $b will be the array
// array(0 => 'a', 1 => 'b', 2 => 'c'), or simply array('a', 'b', 'c').
var_dump($a, $b);
?>
--- Source: array.xml ---
<?php
// Array as (property-)map
$map = array( 'version' => 4,
'OS' => 'Linux',
'lang' => 'english',
'short_tags' => true
);
var_dump($map);
// strictly numerical keys
// this is the same as array(0 => 7, 1 => 8, ...)
$array = array( 7,
8,
0,
156,
-10
);
var_dump($array);
$switching = array( 10, // key = 0
5 => 6,
3 => 7,
'a' => 4,
11, // key = 6 (maximum of integer-indices was 5)
'8' => 2, // key = 8 (integer!)
'02' => 77, // key = '02'
0 => 12 // the value 10 will be overwritten by 12
);
var_dump($switching);
// empty array
$empty = array();
var_dump($empty);
?>
--- Source: array.xml ---
<?php
$colors = array('red', 'blue', 'green', 'yellow');
foreach ($colors as $color) {
echo "Do you like $color?\n";
}
?>
--- Source: array.xml ---
<?php
$colors = array('red', 'blue', 'green', 'yellow');
foreach ($colors as &$color) {
$color = mb_strtoupper($color);
}
unset($color); /* ensure that following writes to
$color will not modify the last array element */
print_r($colors);
?>
--- Source: array.xml ---
<?php
$firstquarter = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>
--- Source: array.xml ---
<?php
// fill an array with all items from a directory
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
var_dump($files);
?>
--- Source: array.xml ---
<?php
sort($files);
print_r($files);
?>
--- Source: array.xml ---
<?php
$fruits = array ( "fruits" => array ( "a" => "orange",
"b" => "banana",
"c" => "apple"
),
"numbers" => array ( 1,
2,
3,
4,
5,
6
),
"holes" => array ( "first",
5 => "second",
"third"
)
);
var_dump($fruits);
// Some examples to address values in the array above
echo $fruits["holes"][5]; // prints "second"
echo $fruits["fruits"]["a"]; // prints "orange"
unset($fruits["holes"][0]); // remove "first"
// Create a new multi-dimensional array
$juices["apple"]["green"] = "good";
var_dump($juices);
?>
--- Source: array.xml ---
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
// $arr1 is still array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
var_dump($arr1, $arr2, $arr3);
?>
--- Source: type-juggling.xml ---
<?php
// int|string
42 --> 42 // exact type
"42" --> "42" // exact type
new ObjectWithToString --> "Result of __toString()"
// object never compatible with int, fall back to string
42.0 --> 42 // float compatible with int
42.1 --> 42 // float compatible with int
1e100 --> "1.0E+100" // float too large for int type, fall back to string
INF --> "INF" // float too large for int type, fall back to string
true --> 1 // bool compatible with int
[] --> TypeError // array not compatible with int or string
// int|float|bool
"45" --> 45 // int numeric string
"45.0" --> 45.0 // float numeric string
"45X" --> true // not numeric string, fall back to bool
"" --> false // not numeric string, fall back to bool
"X" --> true // not numeric string, fall back to bool
[] --> TypeError // array not compatible with int, float or bool
?>
--- Source: type-juggling.xml ---
<?php
$foo = 10; // $foo is an integer
$bar = (bool) $foo; // $bar is a boolean
var_dump($bar);
?>
--- Source: type-juggling.xml ---
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
--- Source: type-juggling.xml ---
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>
--- Source: type-juggling.xml ---
<?php
$foo = 10; // $foo is an integer
$str = "$foo"; // $str is a string
$fst = (string) $foo; // $fst is also a string
// This prints out that "they are the same"
if ($fst === $str) {
echo "they are the same", PHP_EOL;
}
?>
--- Source: type-juggling.xml ---
<?php
$a = 'car'; // $a is a string
$a[0] = 'b'; // $a is still a string
echo $a; // bar
?>
--- Source: declarations.xml ---
<?php
function test(boolean $param) {}
test(true);
?>
--- Source: declarations.xml ---
<?php
function &test(): void {}
?>
--- Source: declarations.xml ---
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
--- Source: declarations.xml ---
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
--- Source: declarations.xml ---
<?php
function foo(): int|INT {} // Disallowed
function foo(): bool|false {} // Disallowed
function foo(): int&Traversable {} // Disallowed
function foo(): self&Traversable {} // Disallowed
use A as B;
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
class_alias('X', 'Y');
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
?>
--- Source: declarations.xml ---
<?php
class C {}
class D extends C {}
// This doesn't extend C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
--- Source: declarations.xml ---
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// This doesn't implement I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
--- Source: declarations.xml ---
<?php
function sum($a, $b): float {
return $a + $b;
}
// Note that a float will be returned.
var_dump(sum(1, 2));
?>
--- Source: declarations.xml ---
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
--- Source: declarations.xml ---
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
--- Source: declarations.xml ---
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
--- Source: declarations.xml ---
<?php
class User {
public static string $foo = 'foo';
public int $id;
public string $username;
public function __construct(int $id, string $username) {
$this->id = $id;
$this->username = $username;
}
}
?>
--- Source: declarations.xml ---
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
--- Source: declarations.xml ---
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// These will be coerced to integers: note the output below!
var_dump(sum(1.5, 2.5));
?>
--- Source: declarations.xml ---
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
--- Source: object.xml ---
<?php
class foo
{
function do_foo()
{
echo "Doing foo.";
}
}
$bar = new foo;
$bar->do_foo();
?>
--- Source: object.xml ---
<?php
$obj = (object) array('1' => 'foo');
var_dump(isset($obj->{'1'})); // outputs 'bool(true)'
// Deprecated as of PHP 8.1
var_dump(key($obj)); // outputs 'string(1) "1"'
?>
--- Source: object.xml ---
<?php
$obj = (object) 'ciao';
echo $obj->scalar; // outputs 'ciao'
?>
--- Source: null.xml ---
<?php
$var = NULL;
?>
--- Source: iterable.xml ---
<?php
function gen(): iterable {
yield 1;
yield 2;
yield 3;
}
foreach(gen() as $value) {
echo $value, "\n";
}
?>
--- Source: string.xml ---
<?php
echo 'this is a simple string', PHP_EOL;
echo 'You can also have embedded newlines in
strings this way as it is
okay to do', PHP_EOL;
// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"', PHP_EOL;
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?', PHP_EOL;
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?', PHP_EOL;
// Outputs: This will not expand: \n a newline
echo 'This will not expand: \n a newline', PHP_EOL;
// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either', PHP_EOL;
?>
--- Source: string.xml ---
<?php
// no indentation
echo <<<END
a
b
c
\n
END;
// 4 spaces of indentation
echo <<<END
a
b
c
END;
--- Source: string.xml ---
<?php
echo <<<END
a
b
c
END;
--- Source: string.xml ---
<?php
// All the following code do not work.
// different indentation for body (spaces) ending marker (tabs)
{
echo <<<END
a
END;
}
// mixing spaces and tabs in body
{
echo <<<END
a
END;
}
// mixing spaces and tabs in ending marker
{
echo <<<END
a
END;
}
--- Source: string.xml ---
<?php
$values = [<<<END
a
b
c
END, 'd e f'];
var_dump($values);
--- Source: string.xml ---
<?php
$values = [<<<END
a
b
END ING
END, 'd e f'];
--- Source: string.xml ---
--- Source: string.xml ---
--- Source: string.xml ---
<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
/* More complex example, with variables. */
class foo
{
var $foo;
var $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': \x41
EOT;
?>
--- Source: string.xml ---
<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>
--- Source: string.xml ---
<?php
// Static variables
function foo()
{
static $bar = <<<LABEL
Nothing in here...
LABEL;
}
// Class properties/constants
class foo
{
const BAR = <<<FOOBAR
Constant example
FOOBAR;
public $baz = <<<FOOBAR
Property example
FOOBAR;
}
?>
--- Source: string.xml ---
<?php
echo <<<"FOOBAR"
Hello World!
FOOBAR;
?>
--- Source: string.xml ---
<?php
echo <<<'EOD'
Example of string spanning multiple lines
using nowdoc syntax. Backslashes are always treated literally,
e.g. \\ and \'.
EOD;
--- Source: string.xml ---
<?php
class foo
{
public $foo;
public $bar;
function __construct()
{
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
$name = 'MyName';
echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41
EOT;
?>
--- Source: string.xml ---
<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>
--- Source: string.xml ---
<?php
$juice = "apple";
echo "He drank some $juice juice." . PHP_EOL;
?>
--- Source: string.xml ---
string-variable::
variable-name (offset-or-property)?
| ${ expression }
offset-or-property::
offset-in-string
| property-in-string
offset-in-string::
[ name ]
| [ variable-name ]
| [ integer-literal ]
property-in-string::
-> name
variable-name::
$ name
name::
[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
--- Source: string.xml ---
<?php
const foo = 'bar';
$foo = 'foo';
$bar = 'bar';
var_dump("${foo}");
var_dump("${(foo)}");
?>
--- Source: string.xml ---
<?php
echo "No interpolation $ has happened\n";
echo "No interpolation $\n has happened\n";
echo "No interpolation $2 has happened\n";
?>
--- Source: string.xml ---
<?php
$juices = array("apple", "orange", "string_key" => "purple");
echo "He drank some $juices[0] juice.";
echo PHP_EOL;
echo "He drank some $juices[1] juice.";
echo PHP_EOL;
echo "He drank some $juices[string_key] juice.";
echo PHP_EOL;
class A {
public $s = "string";
}
$o = new A();
echo "Object value: $o->s.";
?>
--- Source: string.xml ---
<?php
$string = 'string';
echo "The character at index -2 is $string[-2].", PHP_EOL;
$string[-3] = 'o';
echo "Changing the character at index -3 to o gives $string.", PHP_EOL;
?>
--- Source: string.xml ---
<?php
const DATA_KEY = 'const-key';
$great = 'fantastic';
$arr = [
'1',
'2',
'3',
[41, 42, 43],
'key' => 'Indexed value',
'const-key' => 'Key with minus sign',
'foo' => ['foo1', 'foo2', 'foo3']
];
// Won't work, outputs: This is { fantastic}
echo "This is { $great}";
// Works, outputs: This is fantastic
echo "This is {$great}";
class Square {
public $width;
public function __construct(int $width) { $this->width = $width; }
}
$square = new Square(5);
// Works
echo "This square is {$square->width}00 centimeters wide.";
// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";
// Works
echo "This works: {$arr[3][2]}";
echo "This works: {$arr[DATA_KEY]}";
// When using multidimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][2]}";
echo "This works: {$obj->values[3]->name}";
echo "This works: {$obj->$staticProp}";
// Won't work, outputs: C:\directory\{fantastic}.txt
echo "C:\directory\{$great}.txt";
// Works, outputs: C:\directory\fantastic.txt
echo "C:\\directory\\{$great}.txt";
?>
--- Source: string.xml ---
<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str[0];
var_dump($first);
// Get the third character of a string
$third = $str[2];
var_dump($third);
// Get the last character of a string.
$str = 'This is still a test.';
$last = $str[strlen($str)-1];
var_dump($last);
// Modify the last character of a string
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';
var_dump($str);
?>
--- Source: string.xml ---
<?php
$str = 'abc';
$keys = [ '1', '1.0', 'x', '1x' ];
foreach ($keys as $keyToTry) {
var_dump(isset($str[$keyToTry]));
try {
var_dump($str[$keyToTry]);
} catch (TypeError $e) {
echo $e->getMessage(), PHP_EOL;
}
echo PHP_EOL;
}
?>
--- Source: bitwise.xml ---
<?php
/*
* Ignore the top section,
* it is just formatting to make output clearer.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
--------- --------- -- ---------
result value op test
--------- --------- -- ---------
EOH;
/*
* Here are the examples.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Bitwise AND \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Bitwise Inclusive OR \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Bitwise Exclusive OR (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>
--- Source: bitwise.xml ---
<?php
echo 12 ^ 9, PHP_EOL; // Outputs '5'
echo "12" ^ "9", PHP_EOL; // Outputs the Backspace character (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello", PHP_EOL; // Outputs the ascii values #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3", PHP_EOL; // Outputs 1
// 2 ^ ((int) "3") == 1
echo "2" ^ 3, PHP_EOL; // Outputs 1
// ((int) "2") ^ 3 == 1
?>
--- Source: bitwise.xml ---
<?php
/*
* Here are the examples.
*/
echo "\n--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond 0');
echo "\n--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond -1');
echo "\n--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeros fill in right side');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places, 'sign bits get shifted out');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bits shift out left side');
echo "\n--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeros fill in right side');
$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bits shift out left side, including sign bit');
/*
* Ignore this bottom section,
* it is just formatting to make output clearer.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Expression: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Decimal:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binary:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " NOTE: $note\n";
}
echo "\n\n";
}
?>
--- Source: type.xml ---
<?php
class MyClass
{
}
class NotMyClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof NotMyClass);
?>
--- Source: type.xml ---
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>
--- Source: type.xml ---
<?php
class MyClass
{
}
$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>
--- Source: type.xml ---
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>
--- Source: type.xml ---
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'
?>
--- Source: type.xml ---
<?php
$a = 1;
$b = NULL;
$c = fopen('/tmp/', 'r');
var_dump($a instanceof stdClass); // $a is an integer
var_dump($b instanceof stdClass); // $b is NULL
var_dump($c instanceof stdClass); // $c is a resource
var_dump(FALSE instanceof stdClass);
?>
--- Source: type.xml ---
<?php
var_dump(FALSE instanceof stdClass);
?>
--- Source: type.xml ---
<?php
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function getSomeClass(): string
{
return ClassA::class;
}
var_dump(new ClassA instanceof ('std' . 'Class'));
var_dump(new ClassB instanceof ('Class' . 'B'));
var_dump(new ClassC instanceof ('Class' . 'A'));
var_dump(new ClassD instanceof (getSomeClass()));
?>
--- Source: logical.xml ---
<?php
// --------------------
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
// --------------------
// "||" has a greater precedence than "or"
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;
var_dump($e, $f);
// --------------------
// "&&" has a greater precedence than "and"
// The result of the expression (true && false) is assigned to $g
// Acts like: ($g = (true && false))
$g = true && false;
// The constant true is assigned to $h before the "and" operation occurs
// Acts like: (($h = true) and false)
$h = true and false;
var_dump($g, $h);
?>
--- Source: arithmetic.xml ---
<?php
var_dump(5 % 3);
var_dump(5 % -3);
var_dump(-5 % 3);
var_dump(-5 % -3);
?>
--- Source: array.xml ---
<?php
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
$c = $a + $b; // Union of $a and $b
echo "Union of \$a and \$b: \n";
var_dump($c);
$c = $b + $a; // Union of $b and $a
echo "Union of \$b and \$a: \n";
var_dump($c);
$a += $b; // Union of $a += $b is $a and $b
echo "Union of \$a += \$b: \n";
var_dump($a);
?>
--- Source: array.xml ---
<?php
$a = array("apple", "banana");
$b = array(1 => "banana", "0" => "apple");
var_dump($a == $b); // bool(true)
var_dump($a === $b); // bool(false)
?>
--- Source: execution.xml ---
<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>
--- Source: functional.xml ---
<?php
$result = "Hello World" |> strlen(...);
echo $result, PHP_EOL;
$result = strlen("Hello World");
echo $result, PHP_EOL;
?>
--- Source: functional.xml ---
<?php
$result = "PHP Rocks"
|> htmlentities(...)
|> str_split(...)
|> (fn($x) => array_map(strtoupper(...), $x))
|> (fn($x) => array_filter($x, fn($v) => $v != 'O'))
;
print_r($result);
$temp = "PHP Rocks";
$temp = htmlentities($temp);
$temp = str_split($temp);
$temp = array_map(strtoupper(...), $temp);
$temp = array_filter($temp, fn($v) => $v != 'O');
$result = $temp;
print_r($result);
?>
--- Source: comparison.xml ---
<?php
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
switch ("a") {
case 0:
echo "0";
break;
case "a":
echo "a";
break;
}
?>
--- Source: comparison.xml ---
<?php
// Integers
echo 1 <=> 1, ' '; // 0
echo 1 <=> 2, ' '; // -1
echo 2 <=> 1, ' '; // 1
// Floats
echo 1.5 <=> 1.5, ' '; // 0
echo 1.5 <=> 2.5, ' '; // -1
echo 2.5 <=> 1.5, ' '; // 1
// Strings
echo "a" <=> "a", ' '; // 0
echo "a" <=> "b", ' '; // -1
echo "b" <=> "a", ' '; // 1
echo "a" <=> "aa", ' '; // -1
echo "zz" <=> "aa", ' '; // 1
// Arrays
echo [] <=> [], ' '; // 0
echo [1, 2, 3] <=> [1, 2, 3], ' '; // 0
echo [1, 2, 3] <=> [], ' '; // 1
echo [1, 2, 3] <=> [1, 2, 1], ' '; // 1
echo [1, 2, 3] <=> [1, 2, 4], ' '; // -1
// Objects
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b, ' '; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b, ' '; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b, ' '; // 1
// not only values are compared; keys must match
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b, ' '; // 1
?>
--- Source: comparison.xml ---
<?php
// Bool and null are compared as bool always
var_dump(1 == TRUE); // TRUE - same as (bool) 1 == TRUE
var_dump(0 == FALSE); // TRUE - same as (bool) 0 == FALSE
var_dump(100 < TRUE); // FALSE - same as (bool) 100 < TRUE
var_dump(-10 < FALSE);// FALSE - same as (bool) -10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool) NULL < (bool) -100 is FALSE < TRUE
?>
--- Source: comparison.xml ---
<?php
// Arrays are compared like this with standard comparison operators as well as the spaceship operator.
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return 1;
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>
--- Source: comparison.xml ---
<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// The above is identical to this if/else statement
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
--- Source: comparison.xml ---
<?php
// on first glance, the following appears to output 'true'
echo (true ? 'true' : false ? 't' : 'f');
// however, the actual output of the above is 't' prior to PHP 8.0.0
// this is because ternary expressions are left-associative
// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');
// here, one can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool) true, thus returning the true branch of the
// second ternary expression.
?>
--- Source: comparison.xml ---
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
--- Source: comparison.xml ---
<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';
// The above is identical to this if/else statement
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
--- Source: comparison.xml ---
<?php
// Raises a warning that $name is undefined.
print 'Mr. ' . $name ?? 'Anonymous';
// Prints "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>
--- Source: comparison.xml ---
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // outputs 1
?>
--- Source: precedence.xml ---
<?php
$a = 3 * 3 % 5; // (3 * 3) % 5 = 4
var_dump($a);
$a = 1;
$b = 2;
$a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5
var_dump($a, $b);
?>
--- Source: precedence.xml ---
<?php
$a = true ? 0 : (true ? 1 : 2);
var_dump($a);
// this is not allowed since PHP 8
// $a = true ? 0 : true ? 1 : 2;
?>
--- Source: precedence.xml ---
<?php
$a = 1;
echo $a + $a++; // may print either 2 or 3
$i = 1;
$array[$i] = $i++; // may set either index 1 or 2
?>
--- Source: precedence.xml ---
<?php
$x = 4;
// this line might result in unexpected output:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
// this is not allowed, and throws a TypeError:
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
?>
--- Source: precedence.xml ---
<?php
$x = 4;
// this line might result in unexpected output:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// because it is evaluated like this line (prior to PHP 8.0.0):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// the desired precedence can be enforced by using parentheses:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>
--- Source: errorcontrol.xml ---
<?php
$my_file = @file ('non_existent_file') or
die ("Failed opening file: error was '" . error_get_last()['message'] . "'");
?>
--- Source: errorcontrol.xml ---
<?php
// this works for any expression, not just functions:
$value = @$cache[$key];
// will not issue a notice if the index $key doesn't exist.
?>
--- Source: string.xml ---
<?php
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"
var_dump($b);
$a = "Hello ";
$a .= "World!"; // now $a contains "Hello World!"
var_dump($a);
?>
--- Source: increment.xml ---
<?php
echo 'Post-increment:', PHP_EOL;
$a = 5;
var_dump($a++);
var_dump($a);
echo 'Pre-increment:', PHP_EOL;
$a = 5;
var_dump(++$a);
var_dump($a);
echo 'Post-decrement:', PHP_EOL;
$a = 5;
var_dump($a--);
var_dump($a);
echo 'Pre-decrement:', PHP_EOL;
$a = 5;
var_dump(--$a);
var_dump($a);
?>
--- Source: increment.xml ---
<?php
echo '== Alphabetic strings ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// Alphanumeric strings behave differently
echo '== Alphanumeric strings ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
?>
--- Source: increment.xml ---
<?php
$s = "5d9";
var_dump(++$s);
var_dump(++$s);
?>
--- Source: assignment.xml ---
<?php
$a = ($b = 4) + 5; // $a is equal to 9 now, and $b has been set to 4.
var_dump($a);
?>
--- Source: assignment.xml ---
<?php
$a = 3;
$a += 5; // sets $a to 8, as if we had said: $a = $a + 5;
$b = "Hello ";
$b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!";
var_dump($a, $b);
?>
--- Source: assignment.xml ---
<?php
$a = 3;
$b = &$a; // $b is a reference to $a
print "$a\n"; // prints 3
print "$b\n"; // prints 3
$a = 4; // change $a
print "$a\n"; // prints 4
print "$b\n"; // prints 4 as well, since $b is a reference to $a, which has
// been changed
?>
--- Source: assignment.xml ---
<?php
class C {}
$o = &new C;
?>
--- Source: incompatible.xml ---
<?php
class A {
public static function counter() {
static $counter = 0;
$counter++;
return $counter;
}
}
class B extends A {}
var_dump(A::counter()); // int(1)
var_dump(A::counter()); // int(2)
var_dump(B::counter()); // int(3), previously int(1)
var_dump(B::counter()); // int(4), previously int(2)
?>
--- Source: incompatible.xml ---
<?php
function makeyogurt($container = "bowl", $flavour)
{
return "Making a $container of $flavour yogurt.\n";
}
try
{
echo makeyogurt(flavour: "raspberry");
}
catch (Error $e)
{
echo get_class($e), ' - ', $e->getMessage(), "\n";
}
?>
--- Source: new-features.xml ---
<?php
014; // Non-prefix octal literal
0o14; // Prefixed octal literal
?>
--- Source: new-features.xml ---
<?php
$arr1 = [1, 'a' => 'b'];
$arr2 = [...$arr1, 'c' => 'd']; //[1, 'a' => 'b', 'c' => 'd']
?>
--- Source: new-features.xml ---
<?php
$file = new CURLStringFile($data, 'filename.txt', 'text/plain');
curl_setopt($curl, CURLOPT_POSTFIELDS, ['file' => $file]);
?>
--- Source: new-features.xml ---
<?php
$h = hash("murmur3f", $data, options: ["seed" => 42]);
echo $h, "\n";
?>
--- Source: new-features.xml ---
<?php
$h = hash("xxh3", $data, options: ["seed" => 42]);
echo $h, "\n";
?>
--- Source: new-features.xml ---
<?php
$h = hash("xxh3", $data, options: ["secret" => "at least 136 bytes long secret here"]);
echo $h, "\n";
?>
--- Source: new-features.xml ---
<?php
$stmt = $mysqli->prepare('INSERT INTO users(id, name) VALUES(?,?)');
$stmt->execute([1, $username]);
?>
--- Source: new-features.xml ---
<?php
$result = $mysqli->query('SELECT username FROM users WHERE id = 123');
echo $result->fetch_column();
?>
--- Source: new-features.xml ---
<?php
new PDO('sqlite:file:path/to/sqlite.db?mode=ro')
?>
--- Source: deprecated.xml ---
<?php
var_dump(str_contains("foobar", null));
// Deprecated: Passing null to parameter #2 ($needle) of type string
// is deprecated
?>
--- Source: deprecated.xml ---
<?php
$a = [];
$a[15.5]; // deprecated, as key value loses the 0.5 component
$a[15.0]; // ok, as 15.0 == 15
?>
--- Source: deprecated.xml ---
<?php
function &test(): void {}
?>
--- Source: deprecated.xml ---
<?php
$arr = false;
$arr[] = 2; // deprecated
?>
--- Source: deprecated.xml ---
<?php
// From undefined
$arr[] = 'some value';
$arr['doesNotExist'][] = 2;
// From null
$arr = null;
$arr[] = 2;
?>
--- Source: incompatible.xml ---
<?php
var_dump(number_format(-0.01)); // now outputs string(1) "0" instead of string(2) "-0"
--- Source: incompatible.xml ---
<?php
// array to object
$arr = [0 => 1];
$obj = (object) $arr;
var_dump(
$obj,
$obj->{'0'}, // now accessible
$obj->{0} // now accessible
);
--- Source: incompatible.xml ---
<?php
// object to array
$obj = new class {
public function __construct()
{
$this->{0} = 1;
}
};
$arr = (array) $obj;
var_dump(
$arr,
$arr[0], // now accessible
$arr['0'] // now accessible
);
--- Source: incompatible.xml ---
<?php
var_dump(
count(null), // NULL is not countable
count(1), // integers are not countable
count('abc'), // strings are not countable
count(new stdClass), // objects not implementing the Countable interface are not countable
count([1,2]) // arrays are countable
);
--- Source: new-features.xml ---
<?php
function test(object $obj) : object
{
return new SplQueue();
}
test(new stdClass());
--- Source: new-features.xml ---
<?php
abstract class A
{
abstract function test(string $s);
}
abstract class B extends A
{
// overridden - still maintaining contravariance for parameters and covariance for return
abstract function test($s) : int;
}
--- Source: new-features.xml ---
<?php
$db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL);
--- Source: new-features.xml ---
<?php
interface A
{
public function Test(array $input);
}
class B implements A
{
public function Test($input){} // type omitted for $input
}
--- Source: new-features.xml ---
<?php
use Foo\Bar\{
Foo,
Bar,
Baz,
};
--- Source: deprecated.xml ---
<?php
var_dump(NONEXISTENT);
/* Output:
Warning: Use of undefined constant NONEXISTENT - assumed 'NONEXISTENT' (this will throw an Error in a future version of PHP) in %s on line %d
string(11) "NONEXISTENT"
*/
--- Source: incompatible.xml ---
<?php
$str = <<<FOO
abcdefg
FOO
FOO;
?>
--- Source: incompatible.xml ---
<?php
while ($foo) {
switch ($bar) {
case "baz":
continue;
// Warning: "continue" targeting switch is equivalent to
// "break". Did you mean to use "continue 2"?
}
}
?>
--- Source: incompatible.xml ---
<?php
class Test {
public static $x = 0;
}
class Test2 extends Test { }
Test2::$x = &$x;
$x = 1;
var_dump(Test::$x, Test2::$x);
// Previously: int(0), int(1)
// Now: int(1), int(1)
?>
--- Source: incompatible.xml ---
<?php
$arr = [1];
$ref =& $arr[0];
var_dump($arr[0] + ($arr[0] = 2));
// Previously: int(4), Now: int(3)
?>
--- Source: incompatible.xml ---
<?php
function foo(...$args) {
var_dump($args);
}
function gen() {
yield 1.23 => 123;
}
foo(...gen());
?>
--- Source: new-features.xml ---
<?php
mb_strtoupper("Straße");
// Produces STRAßE on PHP 7.2
// Produces STRASSE on PHP 7.3
?>
--- Source: new-features.xml ---
<?php
mb_ereg('(?<word>\w+)', '国', $matches);
// => [0 => "国", 1 => "国", "word" => "国"];
?>
--- Source: new-features.xml ---
<?php
mb_ereg_replace('\s*(?<word>\w+)\s*', "_\k<word>_\k'word'_", ' foo ');
// => "_foo_foo_"
?>
--- Source: new-features.xml ---
<?php
class User {
public int $id;
public string $name;
}
?>
--- Source: new-features.xml ---
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
--- Source: new-features.xml ---
<?php
class A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
?>
--- Source: new-features.xml ---
<?php
/**
* These classes satisfy the LSP requirements, because C is a subtype of A.
* However, at the time class B is declared, class C is not yet available
*/
class A
{
public function method(): A {}
}
class B extends A
{
// Fatal error: Could not check compatibility between B::method():C and
// A::method(): A, because class С is not available
public function method(): С {}
}
class C extends B {}
?>
--- Source: new-features.xml ---
<?php
$array['key'] ??= computeDefault();
// is roughly equivalent to
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
--- Source: new-features.xml ---
<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>
--- Source: new-features.xml ---
<?php
6.674_083e-11; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary
?>
--- Source: new-features.xml ---
<?php
// Returns array containing all the necessary state of the object.
public function __serialize(): array
{
}
// Restores the object state from the given data array.
public function __unserialize(array $data): void
{
}
?>
--- Source: new-features.xml ---
<?php
proc_open(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
?>
--- Source: new-features.xml ---
<?php
// Like 2>&1 on the shell
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
// Like 2>/dev/null or 2>nul on the shell
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
?>
--- Source: deprecated.xml ---
<?php
1 ? 2 : 3 ? 4 : 5; // deprecated
(1 ? 2 : 3) ? 4 : 5; // ok
1 ? 2 : (3 ? 4 : 5); // ok
?>
--- Source: deprecated.xml ---
1 ? 2 ? 3 : 4 : 5 // ok
--- Source: deprecated.xml ---
<?php
// ReflectionClass::export(Foo::class, false) is:
echo new ReflectionClass(Foo::class), "\n";
// $str = ReflectionClass::export(Foo::class, true) is:
$str = (string) new ReflectionClass(Foo::class);
?>
--- Source: incompatible.xml ---
<?php
// Replace
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (error_reporting() == 0) {
return false;
}
// ...
}
// With
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (!(error_reporting() & $err_no)) {
return false;
}
// ...
}
?>
--- Source: incompatible.xml ---
<?php
echo "Sum: " . $a + $b;
// was previously interpreted as:
echo ("Sum: " . $a) + $b;
// is now interpreted as:
echo "Sum:" . ($a + $b);
?>
--- Source: incompatible.xml ---
<?php
// Replace
function test(int $arg = CONST_RESOLVING_TO_NULL) {}
// With
function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
// Or
function test(int $arg = null) {}
?>
--- Source: incompatible.xml ---
<?php
new class extends ParentClass {};
// -> ParentClass@anonymous
new class implements FirstInterface, SecondInterface {};
// -> FirstInterface@anonymous
new class {};
// -> class@anonymous
?>
--- Source: incompatible.xml ---
<?php
class X {
use T1, T2 {
func as otherFunc;
}
function func() {}
}
?>
--- Source: incompatible.xml ---
<?php
trait MyTrait {
abstract private function neededByTrait(): string;
}
class MyClass {
use MyTrait;
// Error, because of return type mismatch.
private function neededByTrait(): int { return 42; }
}
?>
--- Source: incompatible.xml ---
<?php
setlocale(LC_ALL, "de_DE");
$f = 3.14;
echo $f, "\n";
// Previously: 3,14
// Now: 3.14
?>
--- Source: incompatible.xml ---
<?php
// Instead of:
$array{0};
$array{"key"};
// Write:
$array[0];
$array["key"];
?>
--- Source: incompatible.xml ---
<?php
$ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
echo file_get_contents('http://example.org', false, $ctx);
?>
--- Source: new-features.xml ---
<?php
class A {
public function method(int $many, string $parameters, $here) {}
}
class B extends A {
public function method(...$everything) {}
}
?>
--- Source: new-features.xml ---
<?php
class Test {
public function create(): static {
return new static();
}
}
?>
--- Source: new-features.xml ---
<?php
$fn = fn() => throw new Exception('Exception in arrow function');
$user = $session->user ?? throw new Exception('Must have user');
--- Source: new-features.xml ---
<?php
function functionWithLongSignature(
Type1 $parameter1,
Type2 $parameter2, // <-- This comma is now allowed.
) {
}
--- Source: new-features.xml ---
<?php
class ParentClass {
private function method1() {}
private function method2() {}
private static function method3() {}
// Throws a warning, as "final" no longer has an effect:
private final function method4() {}
}
class ChildClass extends ParentClass {
// All of the following are now allowed, even though the modifiers aren't
// the same as for the private methods in the parent class.
public abstract function method1() {}
public static function method2() {}
public function method3() {}
public function method4() {}
}
?>
--- Source: new-features.xml ---
<?php
printf("%.*H", (int) ini_get("precision"), $float);
printf("%.*H", (int) ini_get("serialize_precision"), $float);
?>
--- Source: new-features.xml ---
<?php
$proc = proc_open($command, [['pty'], ['pty'], ['pty']], $pipes);
?>
--- Source: new-features.xml ---
<?php
$proc = proc_open($command, [['socket'], ['socket'], ['socket']], $pipes);
?>
--- Source: new-features.xml ---
<?php
// OK even if $excludes is empty:
array_diff($array, ...$excludes);
// OK even if $arrays only contains a single array:
array_intersect(...$arrays);
?>
--- Source: deprecated.xml ---
<?php
function test($a = [], $b) {} // Before
function test($a, $b) {} // After
?>
--- Source: deprecated.xml ---
<?php
function test(A $a = null, $b) {} // Still allowed
function test(?A $a, $b) {} // Recommended
?>
--- Source: deprecated.xml ---
<?php
// Replace
usort($array, fn($a, $b) => $a > $b);
// With
usort($array, fn($a, $b) => $a <=> $b);
?>
--- Source: deprecated.xml ---
<?php
// iterate using the procedural API
assert(is_resource($zip));
while ($entry = zip_read($zip)) {
echo zip_entry_name($entry);
}
// iterate using the object-oriented API
assert($zip instanceof ZipArchive);
for ($i = 0; $entry = $zip->statIndex($i); $i++) {
echo $entry['name'];
}
?>
--- Source: openssl.xml ---
<?php
$ctx = stream_context_create(['ssl' => [
'capture_session_meta' => TRUE
]]);
$html = file_get_contents('https://google.com/', FALSE, $ctx);
$meta = stream_context_get_options($ctx)['ssl']['session_meta'];
var_dump($meta);
?>
--- Source: openssl.xml ---
openssl dhparam -out /path/to/my/certs/dh-2048.pem 2048
--- Source: openssl.xml ---
<?php
// Requiring TLS 1.0 or better when using file_get_contents():
$ctx = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
],
]);
$html = file_get_contents('https://google.com/', false, $ctx);
// Requiring TLS 1.1 or 1.2:
$ctx = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
],
]);
$html = file_get_contents('https://google.com/', false, $ctx);
// Connecting using the tlsv1.2:// stream socket transport.
$sock = stream_socket_client('tlsv1.2://google.com:443/');
?>
--- Source: openssl.xml ---
<?php
var_dump(openssl_get_cert_locations());
?>
--- Source: openssl.xml ---
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
?>
--- Source: openssl.xml ---
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
var_dump(openssl_spki_verify($spkac));
?>
--- Source: openssl.xml ---
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
$challenge = openssl_spki_export_challenge($spkac);
echo $challenge;
?>
--- Source: openssl.xml ---
<?php
$pkey = openssl_pkey_new();
openssl_pkey_export($pkey, 'secret passphrase');
$spkac = openssl_spki_new($pkey, 'challenge string');
echo openssl_spki_export($spkac);
?>
--- Source: incompatible.xml ---
<?php
class C {
const ONE = 1;
public $array = [
self::ONE => 'foo',
'bar',
'quux',
];
}
var_dump((new C)->array);
?>
--- Source: new-features.xml ---
<?php
const ONE = 1;
const TWO = ONE * 2;
class C {
const THREE = TWO + 1;
const ONE_THIRD = ONE / self::THREE;
const SENTENCE = 'The value of THREE is '.self::THREE;
public function f($a = ONE + self::THREE) {
return $a;
}
}
echo (new C)->f()."\n";
echo C::SENTENCE;
?>
--- Source: new-features.xml ---
<?php
const ARR = ['a', 'b'];
echo ARR[0];
?>
--- Source: new-features.xml ---
<?php
function f($req, $opt = null, ...$params) {
// $params is an array containing the remaining arguments.
printf('$req: %d; $opt: %d; number of params: %d'."\n",
$req, $opt, count($params));
}
f(1);
f(1, 2);
f(1, 2, 3);
f(1, 2, 3, 4);
f(1, 2, 3, 4, 5);
?>
--- Source: new-features.xml ---
<?php
function add($a, $b, $c) {
return $a + $b + $c;
}
$operators = [2, 3];
echo add(1, ...$operators);
?>
--- Source: new-features.xml ---
<?php
printf("2 ** 3 == %d\n", 2 ** 3);
printf("2 ** 3 ** 2 == %d\n", 2 ** 3 ** 2);
$a = 2;
$a **= 3;
printf("a == %d\n", $a);
?>
--- Source: new-features.xml ---
<?php
namespace Name\Space {
const FOO = 42;
function f() { echo __FUNCTION__."\n"; }
}
namespace {
use const Name\Space\FOO;
use function Name\Space\f;
echo FOO."\n";
f();
}
?>
--- Source: new-features.xml ---
<?php
$a = gmp_init(42);
$b = gmp_init(17);
if (version_compare(PHP_VERSION, '5.6', '<')) {
echo gmp_intval(gmp_add($a, $b)), PHP_EOL;
echo gmp_intval(gmp_add($a, 17)), PHP_EOL;
echo gmp_intval(gmp_add(42, $b)), PHP_EOL;
} else {
echo $a + $b, PHP_EOL;
echo $a + 17, PHP_EOL;
echo 42 + $b, PHP_EOL;
}
?>
--- Source: new-features.xml ---
<?php
$expected = crypt('12345', '$2a$07$usesomesillystringforsalt$');
$correct = crypt('12345', '$2a$07$usesomesillystringforsalt$');
$incorrect = crypt('1234', '$2a$07$usesomesillystringforsalt$');
var_dump(hash_equals($expected, $correct));
var_dump(hash_equals($expected, $incorrect));
?>
--- Source: new-features.xml ---
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
--- Source: deprecated.xml ---
<?php
class A {
function f() { echo get_class($this); }
}
class B {
function f() { A::f(); }
}
(new B)->f();
?>
--- Source: incompatible.xml ---
<?php
function test($param){}
test();
--- Source: incompatible.xml ---
<?php
(function () {
$func = 'func_num_args';
$func();
})();
--- Source: incompatible.xml ---
<?php
$a = '';
$a[10] = 'foo';
var_dump($a);
?>
--- Source: incompatible.xml ---
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>
--- Source: incompatible.xml ---
<?php
new DateTime() == new DateTime();
?>
--- Source: incompatible.xml ---
<?php
$f = function () use ($_SERVER) {};
$f = function () use ($this) {};
$f = function ($param) use ($param) {};
--- Source: incompatible.xml ---
<?php
var_dump(json_decode(json_encode(['' => 1])));
--- Source: other-changes.xml ---
<?php
'1b' + 'something';
--- Source: other-changes.xml ---
<?php
var_dump("\500");
--- Source: new-features.xml ---
<?php
function testReturnA(): ?string
{
return 'elePHPant';
}
var_dump(testReturnA());
function testReturnB(): ?string
{
return null;
}
var_dump(testReturnB());
function test(?string $name)
{
var_dump($name);
}
test('elePHPant');
test(null);
test();
--- Source: new-features.xml ---
<?php
function swap(&$left, &$right): void
{
if ($left === $right) {
return;
}
$tmp = $left;
$left = $right;
$right = $tmp;
}
$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);
--- Source: new-features.xml ---
<?php
$data = [
[1, 'Tom'],
[2, 'Fred'],
];
// list() style
list($id1, $name1) = $data[0];
// [] style
[$id1, $name1] = $data[0];
// list() style
foreach ($data as list($id, $name)) {
// logic here with $id and $name
}
// [] style
foreach ($data as [$id, $name]) {
// logic here with $id and $name
}
--- Source: new-features.xml ---
<?php
class ConstDemo
{
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}
--- Source: new-features.xml ---
<?php
function iterator(iterable $iter)
{
foreach ($iter as $val) {
//
}
}
--- Source: new-features.xml ---
<?php
try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}
--- Source: new-features.xml ---
<?php
$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
// list() style
list("id" => $id1, "name" => $name1) = $data[0];
// [] style
["id" => $id1, "name" => $name1] = $data[0];
// list() style
foreach ($data as list("id" => $id, "name" => $name)) {
// logic here with $id and $name
}
// [] style
foreach ($data as ["id" => $id, "name" => $name]) {
// logic here with $id and $name
}
--- Source: new-features.xml ---
<?php
var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));
--- Source: new-features.xml ---
<?php
$string = 'bar';
echo "The last character of '$string' is '$string[-1]'.\n";
?>
--- Source: new-features.xml ---
<?php
class Test
{
public function exposeFunction()
{
return Closure::fromCallable([$this, 'privateFunction']);
}
private function privateFunction($param)
{
var_dump($param);
}
}
$privFunc = (new Test)->exposeFunction();
$privFunc('some value');
--- Source: new-features.xml ---
<?php
pcntl_async_signals(true); // turn on async signals
pcntl_signal(SIGHUP, function($sig) {
echo "SIGHUP\n";
});
posix_kill(posix_getpid(), SIGHUP);
--- Source: new-features.xml ---
<?php
$result = "Hello World" |> strlen(...);
print $result . PHP_EOL; // Prints "11"
--- Source: new-features.xml ---
<?php
#[\NoDiscard]
function concat(string $a, string $b): string {
return $a . $b;
}
// Warning: The return value of function concat() should either be used or
// intentionally ignored by casting it as (void) in xxx.php
concat("a", "b");
// No warning, because the return value is consumed by the assignment.
$results = concat("a", "b");
// No warning, because the (void) cast is used.
(void)concat("a", "b");
--- Source: new-features.xml ---
<?php
const T1 = (int) 0.3; // Previously: "Fatal error: Constant expression contains invalid operations"
print T1 . PHP_EOL; // Prints "0"
--- Source: incompatible.xml ---
<?php
range('9', 'A'); // ["9", ":", ";", "<", "=", ">", "?", "@", "A"], as of PHP 8.3.0
range('9', 'A'); // [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], prior to PHP 8.3.0
?>
--- Source: new-features.xml ---
<?php
/*
On /path/to/user.ini contains the following settings:
listen = localhost:${DRUPAL_FPM_PORT:-9000}
*/
$user_ini = parse_ini_file('/path/to/user.ini');
echo $user_ini['listen']; // localhost:9000
--- Source: incompatible.xml ---
<?php
$xmlString = "<root><a><b>1</b><b>2</b><b>3</b></a></root>";
$xml = simplexml_load_string($xmlString);
$nodes = $xml->a->b;
foreach ($nodes as $nodeData) {
echo "nodeData: " . $nodeData . "\n";
$xml = $nodes->asXml();
}
--- Source: new-features.xml ---
<?php
class Person
{
// A "virtual" property. It may not be set explicitly.
public string $fullName {
get => $this->firstName . ' ' . $this->lastName;
}
// All write operations go through this hook, and the result is what is written.
// Read access happens normally.
public string $firstName {
set => ucfirst(strtolower($value));
}
// All write operations go through this hook, which has to write to the backing value itself.
// Read access happens normally.
public string $lastName {
set {
if (strlen($value) < 2) {
throw new \InvalidArgumentException('Too short');
}
$this->lastName = $value;
}
}
}
$p = new Person();
$p->firstName = 'peter';
print $p->firstName; // Prints "Peter"
$p->lastName = 'Peterson';
print $p->fullName; // Prints "Peter Peterson"
--- Source: new-features.xml ---
<?php
class Example
{
// The first visibility modifier controls the get-visibility, and the second modifier
// controls the set-visibility. The get-visibility must not be narrower than set-visibility.
public protected(set) string $name;
public function __construct(string $name)
{
$this->name = $name;
}
}
--- Source: new-features.xml ---
<?php
class Example
{
public function __construct(private int $data)
{
}
// ...
}
$initializer = static function (Example $ghost): void {
// Fetch data or dependencies
$data = getData();
// Initialize
$ghost->__construct($data);
};
$reflector = new ReflectionClass(Example::class);
$object = $reflector->newLazyGhost($initializer);
--- Source: deprecated.xml ---
<?php
function foo(T1 $a = null) {}
--- Source: deprecated.xml ---
<?php
function foo(T1|null $a = null) {}
--- Source: deprecated.xml ---
<?php
function foo(?T1 $a = null) {}
--- Source: deprecated.xml ---
<?php
function foo(T1 $a, T2 $b = null, T3 $c) {}
--- Source: deprecated.xml ---
<?php
function foo(T1 $a, T2|null $b, T3 $c) {}
--- Source: deprecated.xml ---
<?php
function foo(T1 $a, ?T2 $b, T3 $c) {}
--- Source: deprecated.xml ---
<?php
class _ {}
--- Source: deprecated.xml ---
<?php
class _MyClass {}
--- Source: other-changes.xml ---
<?php
// 'new', 'private', and 'for' were previously unusable
Project::new('Project Name')->private()->for('purpose here')->with('username here');
?>
--- Source: new-features.xml ---
<?php
// Coercive mode
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
--- Source: new-features.xml ---
<?php
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
--- Source: new-features.xml ---
<?php
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
--- Source: new-features.xml ---
<?php
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
--- Source: new-features.xml ---
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
?>
--- Source: new-features.xml ---
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>
--- Source: new-features.xml ---
<?php
echo "\u{aa}", PHP_EOL;
echo "\u{0000aa}", PHP_EOL;
echo "\u{9999}", PHP_EOL;
echo <<<EOT
\u{01f418}
EOT;
?>
--- Source: new-features.xml ---
<?php
class A {private $x = 1;}
// Pre PHP 7 code
$getX = function() {return $this->x;};
$getXCB = $getX->bindTo(new A, 'A'); // intermediate closure
echo $getXCB();
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);
--- Source: new-features.xml ---
<?php
// converts all objects into __PHP_Incomplete_Class object
$data = unserialize($foo, ["allowed_classes" => false]);
// converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
// default behaviour (same as omitting the second argument) that accepts all classes
$data = unserialize($foo, ["allowed_classes" => true]);
--- Source: new-features.xml ---
<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));
--- Source: new-features.xml ---
<?php
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(false, new CustomError('Some error message'));
?>
--- Source: new-features.xml ---
<?php
// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// PHP 7+ code
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
?>
--- Source: new-features.xml ---
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
--- Source: new-features.xml ---
<?php
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
?>
--- Source: new-features.xml ---
<?php
var_dump(intdiv(10, 3));
?>
--- Source: new-features.xml ---
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
?>
--- Source: deprecated.xml ---
<?php
class foo {
function foo() {
echo 'I am the constructor';
}
}
?>
--- Source: deprecated.xml ---
<?php
class foo {
function bar() {
echo 'I am not static!';
}
}
foo::bar();
?>
--- Source: other.xml ---
<?php
class C {}
$c =& new C;
?>
--- Source: other.xml ---
<?php
class A {
public function test() { var_dump($this); }
}
// Note: Does NOT extend A
class B {
public function callNonStaticMethodOfA() { A::test(); }
}
(new B)->callNonStaticMethodOfA();
?>
--- Source: other.xml ---
<?php
echo yield -1;
// Was previously interpreted as
echo (yield) - 1;
// And is now interpreted as
echo yield (-1);
yield $foo or die;
// Was previously interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo) or die;
?>
--- Source: other.xml ---
<?php
function foo($a, $b, $unused, $unused) {
//
}
?>
--- Source: other.xml ---
<?php
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);?>
--- Source: other.xml ---
<?php
switch (1) {
default:
break;
default:
break;
}
?>
--- Source: strings.xml ---
<?php
var_dump("0x123" == "291");
var_dump(is_numeric("0x123"));
var_dump("0xe" + "0x1");
var_dump(substr("foo", "0x1"));
?>
--- Source: strings.xml ---
<?php
$str = "0xffff";
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int) {
throw new Exception("Invalid integer!");
}
var_dump($int); // int(65535)
?>
--- Source: foreach.xml ---
<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
var_dump(current($array));
}
?>
--- Source: foreach.xml ---
<?php
$array = [0];
foreach ($array as &$val) {
var_dump($val);
$array[1] = 1;
}
?>
--- Source: variable-handling.xml ---
<?php
function f() {
// Valid in PHP 5 only.
global $$foo->bar;
// Valid in PHP 5 and 7.
global ${$foo->bar};
}
?>
--- Source: variable-handling.xml ---
<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>
--- Source: variable-handling.xml ---
<?php
list() = $a;
list(,,) = $a;
list($x, list(), $y) = $a;
?>
--- Source: variable-handling.xml ---
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>
--- Source: variable-handling.xml ---
<?php
function getArray() {
return [1, 2, 3];
}
function squareArray(array &$a) {
foreach ($a as &$v) {
$v **= 2;
}
}
// Generates a warning in PHP 7.
squareArray((getArray()));
?>
--- Source: error-handling.xml ---
<?php
// PHP 5 era code that will break.
function handler(Exception $e) { /* ... */ }
set_exception_handler('handler');
// PHP 5 and 7 compatible.
function handler($e) { /* ... */ }
// PHP 7 only.
function handler(Throwable $e) { /* ... */ }
?>
--- Source: integers.xml ---
<?php
var_dump(1 >> -1);
?>
--- Source: integers.xml ---
<?php
var_dump(3/0);
var_dump(0/0);
var_dump(0%0);
?>
--- Source: examples.xml ---
<?php
function fact($x)
{
$return = 1;
for ($i=2; $i <= $x; $i++) {
$return = gmp_mul($return, $i);
}
return $return;
}
echo gmp_strval(fact(1000)) . "\n";
?>
--- Source: intl-get-error-message.xml ---
<?php
if( Collator::getAvailableLocales() === false ) {
show_error( intl_get_error_message() );
}
?>
--- Source: intl-is-failure.xml ---
<?php
function check( $err_code )
{
var_export( intl_is_failure( $err_code ) );
echo "\n";
}
check( U_ZERO_ERROR );
check( U_USING_FALLBACK_WARNING );
check( U_ILLEGAL_ARGUMENT_ERROR );
?>
--- Source: intl-get-error-code.xml ---
<?php
$coll = collator_create( '<bad_param>' );
if( !$coll ) {
handle_error( intl_get_error_code() );
}
?>
--- Source: intl-error-name.xml ---
<?php
$coll = collator_create( 'en_RU' );
$err_code = collator_get_error_code( $coll );
printf( "Symbolic name for %d is %s\n.", $err_code, intl_error_name( $err_code ) );
?>
--- Source: examples.xml ---
<?php
$source = file_get_contents('example.php');
$tokens = token_get_all($source);
foreach ($tokens as $token) {
if (is_string($token)) {
// simple 1-character token
echo $token;
} else {
// token array
list($id, $text) = $token;
switch ($id) {
case T_COMMENT:
case T_DOC_COMMENT:
// no action on comments
break;
default:
// anything else -> output "as is"
echo $text;
break;
}
}
}
?>
--- Source: examples.xml ---
<?php
/* Read local file from /home/bar */
$localfile = file_get_contents("/home/bar/foo.txt");
/* Identical to above, explicitly naming FILE scheme */
$localfile = file_get_contents("file:///home/bar/foo.txt");
/* Read remote file from www.example.com using HTTP */
$httpfile = file_get_contents("http://www.example.com/foo.txt");
/* Read remote file from www.example.com using HTTPS */
$httpsfile = file_get_contents("https://www.example.com/foo.txt");
/* Read remote file from ftp.example.com using FTP */
$ftpfile = file_get_contents("ftp://user:pass@ftp.example.com/foo.txt");
/* Read remote file from ftp.example.com using FTPS */
$ftpsfile = file_get_contents("ftps://user:pass@ftp.example.com/foo.txt");
?>
--- Source: examples.xml ---
<?php
/* Send POST request to https://secure.example.com/form_action.php
* Include form elements named "foo" and "bar" with dummy values
*/
$sock = fsockopen("ssl://secure.example.com", 443, $errno, $errstr, 30);
if (!$sock) die("$errstr ($errno)\n");
$data = "foo=" . urlencode("Value for Foo") . "&bar=" . urlencode("Value for Bar");
fwrite($sock, "POST /form_action.php HTTP/1.0\r\n");
fwrite($sock, "Host: secure.example.com\r\n");
fwrite($sock, "Content-type: application/x-www-form-urlencoded\r\n");
fwrite($sock, "Content-length: " . strlen($data) . "\r\n");
fwrite($sock, "Accept: */*\r\n");
fwrite($sock, "\r\n");
fwrite($sock, $data);
$headers = "";
while ($str = trim(fgets($sock, 4096)))
$headers .= "$str\n";
echo "\n";
$body = "";
while (!feof($sock))
$body .= fgets($sock, 4096);
fclose($sock);
?>
--- Source: examples.xml ---
<?php
/* Create a compressed file containing an arbitrary string
* File can be read back using compress.zlib stream or just
* decompressed from the command line using 'gzip -d foo-bar.txt.gz'
*/
$fp = fopen("compress.zlib://foo-bar.txt.gz", "wb");
if (!$fp) die("Unable to create file.");
fwrite($fp, "This is a test.\n");
fclose($fp);
?>
--- Source: examples.xml ---
<?php
class VariableStream {
var $position;
var $varname;
function stream_open($path, $mode, $options, &$opened_path)
{
$url = parse_url($path);
$this->varname = $url["host"];
$this->position = 0;
return true;
}
function stream_read($count)
{
$ret = substr($GLOBALS[$this->varname], $this->position, $count);
$this->position += strlen($ret);
return $ret;
}
function stream_write($data)
{
$left = substr($GLOBALS[$this->varname], 0, $this->position);
$right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
$GLOBALS[$this->varname] = $left . $data . $right;
$this->position += strlen($data);
return strlen($data);
}
function stream_tell()
{
return $this->position;
}
function stream_eof()
{
return $this->position >= strlen($GLOBALS[$this->varname]);
}
function stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
$this->position = $offset;
return true;
} else {
return false;
}
break;
case SEEK_CUR:
if ($offset >= 0) {
$this->position += $offset;
return true;
} else {
return false;
}
break;
case SEEK_END:
if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
$this->position = strlen($GLOBALS[$this->varname]) + $offset;
return true;
} else {
return false;
}
break;
default:
return false;
}
}
function stream_metadata($path, $option, $var)
{
if($option == STREAM_META_TOUCH) {
$url = parse_url($path);
$varname = $url["host"];
if(!isset($GLOBALS[$varname])) {
$GLOBALS[$varname] = '';
}
return true;
}
return false;
}
}
stream_wrapper_register("var", "VariableStream")
or die("Failed to register protocol");
$myvar = "";
$fp = fopen("var://myvar", "r+");
fwrite($fp, "line1\n");
fwrite($fp, "line2\n");
fwrite($fp, "line3\n");
rewind($fp);
while (!feof($fp)) {
echo fgets($fp);
}
fclose($fp);
var_dump($myvar);
?>
--- Source: zend-thread-id.xml ---
<?php
$thread_id = zend_thread_id();
echo 'Current thread id is: ' . $thread_id;
?>
--- Source: examples.xml ---
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
<title>My lists</title>
<chapter id="books">
<title>My books</title>
<para>
<informaltable>
<tgroup cols="4">
<thead>
<row>
<entry>Title</entry>
<entry>Author</entry>
<entry>Language</entry>
<entry>ISBN</entry>
</row>
</thead>
<tbody>
<row>
<entry>The Grapes of Wrath</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>0140186409</entry>
</row>
<row>
<entry>The Pearl</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>014017737X</entry>
</row>
<row>
<entry>Samarcande</entry>
<entry>Amine Maalouf</entry>
<entry>fr</entry>
<entry>2253051209</entry>
</row>
<!-- TODO: I have a lot of remaining books to add.. -->
</tbody>
</tgroup>
</informaltable>
</para>
</chapter>
</book>
--- Source: examples.xml ---
<?php
class Vegetable {
public $edible;
public $color;
public function __construct($edible, $color = "green")
{
$this->edible = $edible;
$this->color = $color;
}
public function isEdible()
{
return $this->edible;
}
public function getColor()
{
return $this->color;
}
}
?>
--- Source: examples.xml ---
<?php
class Spinach extends Vegetable {
public $cooked = false;
public function __construct()
{
parent::__construct(true, "green");
}
public function cook()
{
$this->cooked = true;
}
public function isCooked()
{
return $this->cooked;
}
}
?>
--- Source: examples.xml ---
<?php
// register autoloader to load classes
spl_autoload_register();
function printProperties($obj)
{
foreach (get_object_vars($obj) as $prop => $val) {
echo "\t$prop = $val\n";
}
}
function printMethods($obj)
{
$arr = get_class_methods(get_class($obj));
foreach ($arr as $method) {
echo "\tfunction $method()\n";
}
}
function objectBelongsTo($obj, $class)
{
if (is_subclass_of($obj, $class)) {
echo "Object belongs to class " . get_class($obj);
echo ", a subclass of $class\n";
} else {
echo "Object does not belong to a subclass of $class\n";
}
}
// instantiate 2 objects
$veggie = new Vegetable(true, "blue");
$leafy = new Spinach();
// print out information about objects
echo "veggie: CLASS " . get_class($veggie) . "\n";
echo "leafy: CLASS " . get_class($leafy);
echo ", PARENT " . get_parent_class($leafy) . "\n";
// show veggie properties
echo "\nveggie: Properties\n";
printProperties($veggie);
// and leafy methods
echo "\nleafy: Methods\n";
printMethods($leafy);
echo "\nParentage:\n";
objectBelongsTo($leafy, Spinach::class);
objectBelongsTo($leafy, Vegetable::class);
?>