$parameter HTML; } print foo( 'PARAMETER' ); print "\n"; function foo($bar) { print "${bar} things\n"; } function bar($x) { return 2 * ${x}; } $foo = function ($a, $b) { return $a * 2; }; function foobar() { return; } /* * The function signature of methods in extended classes and implemented * interfaces has to mirror the parent class/interface. * The overloaded method may not use all params. */ class MyClass { public function something($a, $b) { return $a * 2; } } class MyExtendedClass extends SomeClass { public function something($a, $b) { return $a * 2; } } class MyExtendedClass implements SomeInterface { public function something($a, $b) { return $a * 2; } } /* * Functions may not use all params passed to them. * Report different violations for params *before* and *after* the last param used. */ function something($a) { return 'foobar'; } function myCallback($a, $b, $c, $d) { return $a * $c; } fn ($a, $b, $c) => $b; // phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[] Exception function oneParam(Exception $foo) { return 'foobar'; } function moreParamFirst(Exception $foo, LogicException $bar) { return 'foobar' . $bar; } function moreParamSecond(LogicException $bar, Exception $foo) { return 'foobar' . $bar; } // phpcs:set Generic.CodeAnalysis.UnusedFunctionParameter ignoreTypeHints[] class ConstructorPropertyPromotionNoContentInMethod { public function __construct(protected int $id) {} } class ConstructorPropertyPromotionWithContentInMethod { public function __construct(protected int $id, $toggle = true) { if ($toggle === true) { doSomething(); } } } $found = in_array_cb($needle, $haystack, fn($array, $needle) => $array[2] === $needle); /* * Don't adjust the error code for closures and arrow functions in extended classes/classes implementing interfaces. */ class MyExtendedClass extends SomeClass { public function something($a, $b) { $c = $a + $b; $closure = function ($c, $d) { return $c * 2; }; } } class MyExtendedClass implements SomeInterface { public function something($a, $b) { $c = $a + $b; $fn = fn($c, $d) => $c[2]; } } /** * Magic methods must match the function signature dictated by PHP. * Flagging unused parameters leads to notices which cannot be solved. */ class MagicMethodsWithParams { public function __set(string $name, mixed $value) { // Forbid dynamic properties & overloading inaccessible properties. throw new RuntimeException('Forbidden'); } public function __get(string $name) { throw new RuntimeException('Forbidden'); } public function __isset(string $name) { throw new RuntimeException('Forbidden'); } public function __unset(string $name) { throw new RuntimeException('Forbidden'); } public function __unserialize( array $data ) { // Prevent unserializing from a stored representation of the object for security reasons. $this->instance = new self(); } public static function __set_state(array $properties) { return new self(); } public function __call(string $name, array $arguments) { if (method_exists($this, $name)) { // None of the methods which can be called in this class take arguments, so not passing them. return $this->$name(); } } public static function __callStatic(string $name, array $arguments) { if (method_exists($this, $name)) { // None of the methods which can be called in this class take arguments, so not passing them. return self::$name(); } } } /** * Unused parameters in magic methods which have flexible function signatures should still be flagged. */ class MagicMethodsWithParamsNotDictatedByPHP { public $foo; public function __construct($foo, $bar, $baz) { $this->foo = $foo; } public function __invoke($foo, $bar, $baz) { $this->foo = $foo; } } /** * Unused parameters in magic methods which have flexible function signatures * where the method potentially overloads a parent method should still be flagged, * but should use the `FoundInExtendedClassAfterLastUsed` error code. */ class MagicMethodsWithParamsNotDictatedByPHPInChildClass extends SomeParent{ public $foo; public function __construct($foo, $bar, $baz) { $this->foo = $foo; } public function __invoke($foo, $bar, $baz) { $this->foo = $foo; } } /** * Methods that throw an exception or return on the first line and are part * of a class that implements an interface should not trigger the sniff. */ class InterfaceMethodNotImplement implements SomeInterface { public function notImplemented($param) { throw new Exception('Not implemented.'); } public function notImplemented2($param) { return 'Not implemented.'; } } /** * Should trigger the sniff as this method is not part of an interface. */ class MethodThrowsException { public function throwsException($param) { throw new Exception(); } }