function query( PDO|PDOInterface $db, // same syntax as multi-catch string $query, ?array $params = [] ): array|int { // do stuff }
function query( PDO|PDOInterface $db, string|Stringable $query, // anything with __toString() ?array $params = [] ): array|int { // do stuff }
interface DoesAThing { function doAThing(mixed $thisCouldBeAnything): mixed;
# string|int|float|bool|null|array|object|callable|resource
}
query(query: 'SELECT 1', db: $pdo);
query(
$pdo,
params: ['one', 'two'],
query: 'SELECT * FROM notes WHERE slug IN (?, ?)'
);
If you're writing a library, you have a whole new class of BC breaks to think about.
interface NoteRepo {
public function findBySlug(string $slug): ?Note;
}
class Note { public Author $author; }
class Author { public string $name; }
$notes->findBySlug('nonexistent')?->author->name; // ?string
switch (getRoute()) { case '/home': case '/': $title = 'Home Page'; break; case '/profile': $title = getUserName(); break; default: $title = 'My Great App!'; }
$title = match (getRoute()) {
'/home', '/' => 'Home Page',
'/profile' => getUserName(),
default => 'My Great App!'
};
class DbColumn
{
public function __construct(
private string $name,
private bool $nullable = false
) {
echo $this->name . ' is '
. ($nullable ? '' : 'not ')
. "nullable\n";
}
}
#[Attribute]
class DbColumn { public function __construct( private string $name, private bool $nullable = false ) {} } class Note { #[DbColumn('name')] public string $name; } $dbColumn = (new ReflectionClass('Note')) ->getProperties()[0] // $name property ->getAttributes()[0] // DbColumn ReflectionAttribute ->newInstance(); // DbColumn object with properties set
try {
$api = API::connect();
// do stuff with $api
} catch (BadApiKey) {
// The type of the exception is enough to decide what
// to do here, so we don't need the exception itself.
}