Created
March 28, 2018 20:16
-
-
Save nathan-fiscaletti/b532809b38810d4fbfbb9ff9027be253 to your computer and use it in GitHub Desktop.
Simple multi-type return functions with strict typing and type coercion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class MyClass | |
{ | |
private $data; | |
public function __construct(array $value) | |
{ | |
$this->data = $value; | |
} | |
public static function __coerce($value) | |
{ | |
if (! is_array($value)) { | |
throw new \Exception( | |
'Returned value does not match the return type defined.' | |
); | |
} | |
return new self($value); | |
} | |
} | |
class MRFClass { | |
function callMe($name) | |
{ | |
return [$name, 1, 2, 3]; | |
} | |
} | |
/** | |
* Call a global function and use type coercion | |
* for non-registered return types. | |
* | |
* @param closure $closure The function to execute. | |
* @param string $returnType The registered return type. | |
* @param array $params The parameters to pass to the function. | |
* | |
* @return mixed The result of the function to execute. | |
*/ | |
function multiReturnFunction($closure, $returnType, ...$params) | |
{ | |
$val = $closure(...$params); | |
if (gettype($val) === 'object') { | |
if (get_class($val) != $returnType) { | |
if (method_exists($returnType, '__coerce')) { | |
$val = $returnType::__coerce($val); | |
} else { | |
throw new \Exception( | |
'Returned value does not match the return type defined, '. | |
'and no __coerce function is visible.' | |
); | |
} | |
} | |
} else if (gettype($val) != $returnType) { | |
if (method_exists($returnType, '__coerce')) { | |
$val = $returnType::__coerce($val); | |
} else { | |
throw new \Exception( | |
'Returned value does not match the return type defined, '. | |
'and no __coerce function is visible.' | |
); | |
} | |
} | |
return $val; | |
} | |
/* | |
* Call a class method and use type coercion | |
* for non-registered return types. | |
* | |
* @param object $obj The object to call the method on. | |
* @param string $method The method to call on the object. | |
* @param string $returnType The registered return type. | |
* @param array $params The parameters to pass to the method. | |
* | |
* @return mixed The result of the method to execute. | |
*/ | |
function multiReturnMethod($obj, $method, $returnType, ...$params) | |
{ | |
$val = $obj->{$method}(...$params); | |
if (gettype($val) === 'object') { | |
if (get_class($val) != $returnType) { | |
if (method_exists($returnType, '__coerce')) { | |
$val = $returnType::__coerce($val); | |
} else { | |
throw new \Exception( | |
'Returned value does not match the return type defined, '. | |
'and no __coerce function is visible.' | |
); | |
} | |
} | |
} else if (gettype($val) != $returnType) { | |
if (method_exists($returnType, '__coerce')) { | |
$val = $returnType::__coerce($val); | |
} else { | |
throw new \Exception( | |
'Returned value does not match the return type defined, '. | |
'and no __coerce function is visible.' | |
); | |
} | |
} | |
return $val; | |
} | |
$resultingMyClass = multiReturnFunction ( | |
// Multi return type function. | |
function($name, $age) { | |
// Here you can return either a MyClass instance, or an array. | |
// All other types will throw an exception. | |
return [$name, $age]; | |
}, | |
// Return Type, any other type will be coerced through this class. | |
MyClass::class, | |
// Function parameters. | |
'Nathan', 23 | |
); | |
print_r($resultingMyClass); | |
$resultingMRFClass = multiReturnMethod ( | |
// The object that we will be calling the | |
// class method on. | |
new MRFClass(), | |
// The class method to call, by name. | |
// This can return either a MyClass instance or an array. | |
'callMe', | |
// The return type to coerce to. | |
MyClass::class, | |
// The function parameters. | |
'Nathan' | |
); | |
print_r($resultingMRFClass); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See instructions on usage here: https://stackoverflow.com/questions/48119027/php-override-weak-function-return-type-coercion/49542067#49542067