Let's say you have a file like this:
<?php
declare(strict_types=1);
class Foo
{
protected $x;
public function __construct(array $x = [])
{
$this->x = $x;
}
public function bar(int $y): string
{
if (!array_key_exists($y, $this->z)) {
throw new Exception("Key not found");
}
}
public function baz(string $y): int
{
foreach ($this->x as $key => $value) {
if ($y === $value) {
return $key;
}
}
throw new Exception("Value not found");
}
}
PHP 7 enforces strictness on a per-file basis. So even though you're using them, if someone writes another script that calls it like this, it will work:
<?php
require "src/Foo.php";
$data = new Foo(['a', 'b', 'c', 'def']);
var_dump($data->bar('2')); // string(1) "c"
If you wanted to be completely hostile towards your users and demand they use strict types, here's how you do it:
<?php
declare(strict_types=1);
class Foo
{
protected $x;
public function __construct(array $x = [])
{
$this->x = $x;
}
// Notice: No parameter type declarations
public function bar($y): string
{
return $this->actualBar($y);
}
// Notice: No parameter type declarations
public function baz($y): int
{
return $this->actualBaz($y);
}
protected function actualBar(int $y): string
{
if (!array_key_exists($y, $this->z)) {
throw new Exception("Key not found");
}
}
protected function actualBaz(string $y): int
{
foreach ($this->x as $key => $value) {
if ($y === $value) {
return $key;
}
}
throw new Exception("Value not found");
}
Because the public API doesn't enforce types, PHP won't use weakly-typed conversion rules. It will pass them wholesale.
Then, when your public API methods (which exist in bat country a.k.a. strict_types=1 land) pass them to your protected methods, the strict types rules will be enforced. And thus, TypeError
gets thrown, regardless of your user's type preference.
Strict scalar type checking is done from the consumer perspective. This approach shifts the consumer into your code, which then triggers strict hints anyway.
As a negative side, the reflection of the type hints is lost, as well as interface compatibility (should your interfaces have scalar hints in them), so it is overall a bad solution, IMO.