Skip to content

Instantly share code, notes, and snippets.

@nathan-fiscaletti
Created March 28, 2018 20:16
Show Gist options
  • Save nathan-fiscaletti/b532809b38810d4fbfbb9ff9027be253 to your computer and use it in GitHub Desktop.
Save nathan-fiscaletti/b532809b38810d4fbfbb9ff9027be253 to your computer and use it in GitHub Desktop.
Simple multi-type return functions with strict typing and type coercion
<?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