What's new in PHP land? 2023.2

@brisphp1

https://brisphp.com

#BrisPHP

Giveaway: brisphp.com/pizza

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
var_dump(unserialize('i:5;i:6;'));
// Warning: unserialize(): Extra data starting at offset 4 of 8 bytes
// int(5)
 
var_dump(unserialize('N;i:6;'));
// Warning: unserialize(): Extra data starting at offset 2 of 6 bytes
// NULL
 
var_dump(unserialize('b:1;i:6;'));
// Warning: unserialize(): Extra data starting at offset 4 of 8 bytes
// bool(true)
 
var_dump(unserialize('a:1:{s:3:"foo";b:1;}i:6;'));
// Warning: unserialize(): Extra data starting at offset 20 of 24 bytes
// array(1) {
//   ["foo"]=>
//   bool(true)
// }

PHP 8.3: unserialize warning

@brisphp1

https://brisphp.com

#BrisPHP

class Test {
    private const int A = 1;
    public const mixed B = 1;
    public const int C = 1;
    public const Foo|Stringable|null D = null;
}
 
class Test2 extends Test {
    // This is legal since Test::A is private
    public const string A = 'a';
 
    // This is legal since int is a subtype of mixed
    public const int B = 0;
 
    // This is illegal since mixed is a supertype of int
    public const mixed C = 0;
 
    // This is legal since Foo&Stringable is more restrictive than Foo|Stringable
    public const (Foo&Stringable)|null D = null;
}

PHP 8.3: Typed class constants

@brisphp1

https://brisphp.com

#BrisPHP

class Foo {
    public function __construct(
        public readonly DateTime $bar,
        public readonly DateTime $baz
    ) {}
 
    public function __clone()
    {
        $this->bar = clone $this->bar; // Works
        $this->cloneBaz();
    }
 
    private function cloneBaz()
    {
        unset($this->baz); // Also works
    }
}
 
$foo = new Foo(new DateTime(), new DateTime());
$foo2 = clone $foo;
 
// Foo2::$bar is cloned deeply
// Foo2::$baz becomes uninitialized

PHP 8.3: Readonly amendments

@brisphp1

https://brisphp.com

#BrisPHP

readonly class A
{
    public function doStuff()
    {
        // ...
    }
}
 
class B extends A
{
    private int $doStuffCounter = 0;
 
    public function doStuff()
    {
        ++$this->doStuffCounter;
 
        parent::doStuff();
    }
 
    public function getDoStuffCounter(): int
    {
        return $this->doStuffCounter;
    }
}

PHP 8.3: Readonly amendments (failed)

@brisphp1

https://brisphp.com

#BrisPHP

function foo() {
    static $i = 1;
    echo $i++, "\n";
}
 
foo(); 
// 1
foo(); 
// 2
foo(); 
// 3

PHP 8.3: Arbitrary static value initializers

@brisphp1

https://brisphp.com

#BrisPHP

function bar() {
    echo "bar() called\n";
    return 1;
}
 
function foo() {
    static $i = bar();
    echo $i++, "\n";
}
 
foo();
// bar() called
// 1
foo();
// 2
foo();
// 3

PHP 8.3: Arbitrary static value initializers

@brisphp1

https://brisphp.com

#BrisPHP

function foo() {
    static $x = 1;
    var_dump($x);
    static $x = 2;
    var_dump($x);
}
 
foo();
// Previously:
//   2
//   2

// Now:
//   Fatal error: Duplicate declaration of static variable $x

PHP 8.3: Arbitrary static value initializers

@brisphp1

https://brisphp.com

#BrisPHP

$input = [1, 2, 3, 4];

$output = array_sum($input);
// 10
$output = array_reduce($input, fn($carry, $value) => $carry + $value, 0);
// 10


$output = array_product($input);
// 24
$output = array_reduce($input, fn($carry, $value) => $carry * $value, 1);
// 24

PHP 8.3: Saner array_(sum|product)

@brisphp1

https://brisphp.com

#BrisPHP

$input = ["1", "2", "3", "4"];

$output = array_sum($input);
// 10
$output = array_reduce($input, fn($carry, $value) => $carry + $value, 0);
// 10


$output = array_product($input);
// 24
$output = array_reduce($input, fn($carry, $value) => $carry * $value, 1);
// 24

PHP 8.3: Saner array_(sum|product)

@brisphp1

https://brisphp.com

#BrisPHP

$input = ["1", "2", "3", "four"];

$output = array_sum($input);
// 6
$output = array_reduce($input, fn($carry, $value) => $carry + $value, 0);
// Fatal error


$output = array_product($input);
// 0
$output = array_reduce($input, fn($carry, $value) => $carry * $value, 1);
// Fatal error

PHP 8.3: Saner array_(sum|product)

PhpUnit 10

  • Massive cleanup, refactoring, and modernisation
  • TestListener & TestHook replaced with Events
  • Test outcome and issues are now separate
    • No longer converting warnings to exceptions
  • Attribute support added

Researcher hijacks packages

  • Hacked 4 inactive Packagist accounts
  • Forked 14 repositories managed by the accounts
  • Updated Packagist to point to the fork
  • Only changed the package description
  • Was trying to "get a job" 🙄
  • Repositories include
    • 3 Acme PHP packages
    • 5 Doctrine packages
  • Edits to packages with 50,000 installs disabled
  • Plan to make audit logs publicly accessible

Questions?

@brisphp1

https://brisphp.com

#BrisPHP

Observability Panel

  • Justin Hennessy
  • Ben Plunkett
  • Damian Maclennan
Made with Slides.com