Skip to content

Instantly share code, notes, and snippets.

@jsor
Last active December 20, 2015 04:18
Show Gist options
  • Save jsor/6069419 to your computer and use it in GitHub Desktop.
Save jsor/6069419 to your computer and use it in GitHub Desktop.
Interfaces for functions.
<?php
require __DIR__.'/function_interfaces.php';
interface foo {}
interface interfaces {
function my_function();
function my_function2(callable $callable, $string, \Traversable $traversable, foo $foo, $constant = DIRECTORY_SEPARATOR);
}
// True
var_dump(function_interfaces\function_implements(function () {
}, 'interfaces::my_function'));
// True - Empty interfaces are _always_ implemented
var_dump(function_interfaces\function_implements(function ($param) {
}, 'interfaces::my_function'));
// False
var_dump(function_interfaces\function_implements(function () {
}, 'interfaces::my_function2'));
// True
var_dump(function_interfaces\function_implements(function (callable $callable, $string, \Traversable $traversable, foo $foo, $constant = DIRECTORY_SEPARATOR) {
}, 'interfaces::my_function2'));
// True - Parameter names don't matter
var_dump(function_interfaces\function_implements(function (callable $callable2, $string2, \Traversable $traversable2, foo $foo2, $constant2 = DIRECTORY_SEPARATOR) {
}, 'interfaces::my_function2'));
<?php
namespace function_interfaces;
// Inspired by https://github.com/ircmaxell/Protocol-Lib
function function_implements($function, $interface)
{
$interfaceReflectionMethod = new \ReflectionMethod($interface);
$functionParameters = (new \ReflectionFunction($function))->getParameters();
$checkParam = function($param1, $param2) {
foreach (array(
'isArray',
'isCallable',
'isDefaultValueAvailable',
'isDefaultValueConstant',
'isOptional',
'isPassedByReference',
'canBePassedByValue',
'getDefaultValue',
'getDefaultValueConstantName',
'allowsNull',
'getClass',
) as $check) {
try {
// Do loose comparision, otherwise ReflectionParameter::getClass
// check will return false
if ($param1->$check() != $param2->$check()) {
return false;
}
} catch (\ReflectionException $e) {
// Some methods throw exceptions when a parameter is typehinted
// with a internal class, array or callable.
// * ReflectionParameter::getDefaultValue
// * ReflectionParameter::getDefaultValueConstantName
// * ReflectionParameter::isDefaultValueConstant
// See: http://www.php.net/manual/en/reflectionparameter.getdefaultvalue.php#refsect1-reflectionparameter.getdefaultvalue-notes
if ('Internal error: Failed to retrieve the default value' !== $e->getMessage()) {
return false;
}
}
}
return true;
};
foreach ($interfaceReflectionMethod->getParameters() as $key => $param) {
if (!isset($functionParameters[$key])) {
return false;
}
if (!$checkParam($param, $functionParameters[$key])) {
return false;
}
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment