What's new in PHP land? 2023.3

@brisphp1

https://brisphp.com

#BrisPHP

Giveaway: brisphp.com/pizza

@brisphp1

https://brisphp.com

#BrisPHP

<?php


var_dump(null + 1); // int(1)

var_dump(null - 1); // int(-1)
 
 
var_dump(false + 1); // int(1)

var_dump(false - 1); // int(-1)
 
 
var_dump(true + 1); // int(2)

var_dump(true - 1); // int(0)

PHP 8.3: Increment/Decrement

<?php
 
$null = null;
var_dump(++$null); // int(1)
$null = null;
var_dump(--$null); // NULL
 
$false = false;
var_dump(++$false); // bool(false)
$false = false;
var_dump(--$false); // bool(false)
 
$true = true;
var_dump(++$true); // bool(true)
$true = true;
var_dump(--$true); // bool(true)

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
 
var_dump("10" + 1); // int(11)

var_dump("10" - 1); // int(9)


var_dump("5.7" + 1); // float(6.7)

var_dump("5.7" - 1); // float(4.7)


var_dump("aa" + 1); // TypeError

var_dump("aa" - 1); // TypeError

PHP 8.3: Increment/Decrement

<?php
 
$stringInt = "10";
var_dump(++$stringInt); // int(11)
$stringInt = "10";
var_dump(--$stringInt); // int(9)

$stringFloat = "5.7";
var_dump(++$stringFloat); // float(6.7)
$stringFloat = "5.7";
var_dump(--$stringFloat); // float(4.7)

$string = "aa";
var_dump(++$string); // string(2) "ab"
$string = "aa";
var_dump(--$string); // string(2) "aa"

@brisphp1

https://brisphp.com

#BrisPHP

PHP 8.3: Increment/Decrement

<?php
 
// Carrying values of different cases/types
$s = "Az";
var_dump(++$s); // string(2) "Ba"
$s = "aZ";
var_dump(++$s); // string(2) "bA"
$s = "A9";
var_dump(++$s); // string(2) "B0"
$s = "a9";
var_dump(++$s); // string(2) "b0"
 
// Carrying values until the beginning of the string
$s = "Zz";
var_dump(++$s); // string(3) "AAa"
$s = "zZ";
var_dump(++$s); // string(3) "aaA"
$s = "9z";
var_dump(++$s); // string(3) "10a"
$s = "9Z";
var_dump(++$s); // string(3) "10A"

@brisphp1

https://brisphp.com

#BrisPHP

<?php


var_dump("" + 1); // TypeError

var_dump("" - 1); // TypeError

PHP 8.3: Increment/Decrement

<?php
 
$emptyString = "";
var_dump(++$emptyString); // string(1) "1"
$emptyString = "";
var_dump(--$emptyString); // int(1) "1"

@brisphp1

https://brisphp.com

#BrisPHP

PHP 8.3: Increment/Decrement

Now

  • add str_increment() and str_decrement()
  • E_WARNING when nothing happens
  • Deprecate decrement on non-numeric strings
  • Deprecate increment on non-alphanumeric strings

Later

  • Deprecate increment on non-numeric strings
  • bool & null are first cast to integers
  • TypeError for non-numeric strings

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
interface Formatter {
  public function format(string $input): string;
  public function isSupported(string $input): bool;
}
 
trait DefaultFormatter {
  public function format(string $input): string {...}
 
  public function isSupported(string $Input): bool {...}
}
 
final class LengthRestrictedFormatter {
  use DefaultFormatter;
 
  public function __construct(private int $maxLength) {}
 
  /* Intention is to override isSupported... */
  public function isValid(string $input): bool {...}
}

PHP 8.3: #[\Override]

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
namespace MyApp\Tests;
 
use PHPUnit\Framework\TestCase;
 
final class MyTest extends TestCase
{
    protected bool $myProp;
 
    /* Typo: will never be called */
    protected function setUpp(): void
    {
        $this->myProp = true;
    }
 
    public function testItWorks(): void
    {
        $this->assertTrue($this->myProp);
    }
}

PHP 8.3: #[\Override]

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
interface StringValidator {
  public function validate(string $input): bool;
}
 
final class NonEmptyValidator implements StringValidator {
  public function validate(string $input): bool
  {
    return $input !== '';
  }
 
  /* Used to be in the interface, but has since been removed */
  public function getIdentifierForErrorMessage(): string
  {
    return 'string_must_not_be_empty';
  }
}

PHP 8.3: #[\Override]

@brisphp1

https://brisphp.com

#BrisPHP

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Http;
 
class RssFeed extends Model {
  /* 
   * Laravel 5.4 added the refresh() method to Eloquent,
   * but we already had it doing something different.
   */
  public function refresh()
  {
    $this->message = Http::get($this->url);
    $this->save();
  }
}

PHP 8.3: #[\Override]

@brisphp1

https://brisphp.com

#BrisPHP

PHP 8.3: #[\Override]

  • #[\Override] expresses intent
  • Fatal error if method doesn't exist
  • Better BC than a keyword
  • Keywords affect behaviour of children
  • Catches typos and using incorrect method names
  • Lets you know when you remove dead code
  • WON'T catch new methods added to a parent
    • Static analysis could catch this

rfc.stitcher.io

Questions?

@brisphp1

https://brisphp.com

#BrisPHP

Observability Panel

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