PHP : anonymous function in associative array - php

Is is possible? Something like (which doesn't work) :
$prototype = array(
'ext' => function ($args)
{
$ext = NULL;
if (in_array(func_get_arg(0), array('js', 'css')))
return $ext;
else
return 'js';
},
);

Yes. The only limitation is that you can't cast it to an object.
<?php
$foo = array(
'bar' => function($text)
{
echo $text;
}
);
$foo['bar']('test'); //prints "test"
$obj = (object)$foo;
$obj->bar('test'); //Fatal error: Call to undefined method stdClass::bar() in /code/REGnPf on line 11
?>

It certainly is:
<?php
$array = array(
'func' => function($a) {
return $a + 2;
}
);
echo $array['func'](3);
?>
This will give you 5 =)!

Related

Is it possible to define functions under stdClass

Here i tried to define a function under stdClass object.
<?php
$x= function($name){return "Hello ".$name;};
echo $x("Sun");
$hey = (object)[ "x" => function($name){return "Hello ".$name;}, "y" =>"Hello Venus"];
echo $hey->x("Mercury");
echo $hey->y;
But it says: Fatal error: Call to undefined method stdClass::x()
This is the closest you can get:
$x = function ($name) { return 'hello ' . $name; };
$obj = new stdClass();
$obj->x = $x;
echo call_user_func($obj->x, 'john'); // this will work
echo $obj->x('john'); // this will not work
You won't need to use call_user_func with php7 though.

Creating a function from a variable

I am attempting to run a function named from a variable. There is no syntax error. Temperature is not returned. I don't know for certain if the problem is with the function itself or the eval. Variations on the eval theme have not worked so far.
function getBtemp($lum, $sub){
$tempsB = array(
"V" => array( 30000, 25400, ... ),
"III" => array( 29000, 24000, ... ),
"I" => array( 26000, 20800, ... ) );
if($lum == "VI"){ $lum = "V"; }
else if($lum == "IV"){ $lum = "III"; }
else if($lum == "II" || $lum == "Ib" || $lum == "Ia" ){ $lum = "V"; }
return $tempsB['$lum']['$sub']; }
// Variables:
$spectralclass = "B";
$luminosityclass = "V";
$subclass = 5;
// Needed:
$temp = getBtemp($luminosityclass, $subclass);
// Functions are named from spectral class, e.g. get.$spectralclass.temp()
// Attempt:
$str = "$temp = get".$spectralclass."temp($luminosityclass, $subclass);";
eval($str);
Try doing this:
$func = 'get'.$spectralclass.'temp';
$temp = $func($luminosityclass, $subclass);
You might be better off doing something like
$functionName = 'get' . $spectralclass . 'temp';
$temp = $functionName($luminosityclass, $subclass);
This is what the PHP manual calls a "variable function". In most cases PHP lets you treat a string variable as a function name, and doing so is a bit safer (more restrictive, less error-prone) than eval.
You need to pass parameters after set function name. See a sample:
function getAtemp($a = 'default') {
echo $a;
}
$name = 'Trest';
$function = 'A';
$temp = 'get' . $function . 'temp';
echo($temp('teste'));
Additionally, read from Eric Lippert: Eval is Evil
Replace the following line:
$str = "$temp = get".$spectralclass."temp($luminosityclass, $subclass);";
by
$str = '$temp = get'.$spectralclass.'temp($luminosityclass, $subclass);';
or
$str = "\$temp = get".$spectralclass."temp(\$luminosityclass, \$subclass);";
See http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double

text1/text2 to array['text1']['text2']?

I'm trying to make something like
function config( $string ){
require 'configuration.php';
return $config[$string];
}
but i have a problem when my config has a 2D array. like:
$config['features'] = array(
'memcached' => TRUE,
'compress' => TRUE,
'gzip' => TRUE
);
how can i get config('features/memcached') or if can we have three or more threaded array like config('features/memcached/version14/etc') ( example ) to return true but still works when we do something like config('features') returns the array just like the function above. any ideas ?
Just split the string into keys:
function config( $string ){
require 'configuration.php';
$keys = explode('/',$string);
$return = $config;
foreach($keys as $key){
$return = $return[$key];
}
return $return;
}
Here you can do this too:
config('features/others/foo/bar');
if this exists:
$config['features'] = array(
'memcached' => TRUE,
'others' => array( 'foo' => array( 'bar' => 42 ) )
);
function config( $string ){
require 'configuration.php';
$p = explode("/",$string);
$r = $config;
foreach($p as $param)
$r = $r[$param];
return $r;
}
you could try this (written from head, not tested):
function config( $key, $subkey = null ){
require 'configuration.php';
return ($subkey)? $config[$key][$subkey] : $config[$key];
}
use it as config('features','memcached') and note that this will only work with one level of sub-arrays. if there could be more or if you want to stick to the config('features/memcached')-syntax, you could try something like this (same as the function above - this isn't tested, maybe you'll have to fix a bug on your own ;) ):
function config( $string ){
require 'configuration.php';
$keys = explode('/',$string);
foreach($keys as $key){
$config = $config[$key];
}
return $config;
}
You can use that aproach:
public function config($path = null, $separator = '.')
{
if (!$path) {
return self::$_constants;
}
$keys = explode($separator, $path);
require 'configuration.php';
$value = $config;
foreach ($keys as $key) {
if (!isset($value[$key])) {
throw new Exception("Value for path $path doesn't exists or it's null");
}
$value = $value[$key];
}
return $value;
}
In your example calling config('features') will return array, and config('features.compres') will return true and so on.

getting function's argument names

In PHP Consider this function:
function test($name, $age) {}
I need to somehow extract the parameter names (for generating custom documentations automatically) so that I could do something like:
get_func_argNames('test');
and it would return:
Array['name','age']
Is this even possible in PHP?
You can use Reflection :
function get_func_argNames($funcName) {
$f = new ReflectionFunction($funcName);
$result = array();
foreach ($f->getParameters() as $param) {
$result[] = $param->name;
}
return $result;
}
print_r(get_func_argNames('get_func_argNames'));
//output
Array
(
[0] => funcName
)
It's 2019 and no one said this?
Just use get_defined_vars():
class Foo {
public function bar($a, $b) {
var_dump(get_defined_vars());
}
}
(new Foo)->bar('first', 'second');
Result:
array(2) {
["a"]=>
string(5) "first"
["b"]=>
string(6) "second"
}
This is an old question I happened on looking for something other then Reflection, but I will toss out my current implementation so that it might help someone else. Using array_map
For a method
$ReflectionMethod = new \ReflectionMethod($class, $method);
$params = $ReflectionMethod->getParameters();
$paramNames = array_map(function( $item ){
return $item->getName();
}, $params);
For a function
$ReflectionFunction = new \ReflectionFunction('preg_replace');
$params = $ReflectionFunction->getParameters();
$paramNames = array_map(function( $item ){
return $item->getName();
}, $params);
echo '<pre>';
var_export( $paramNames );
Outputs
array(
'0' => 'regex',
'1' => 'replace',
'2' => 'subject',
'3' => 'limit',
'4' => 'count'
)
Cheers,
In addition to Tom Haigh's answer if you need to get the default value of optional attributes:
function function_get_names($funcName){
$attribute_names = [];
if(function_exists($funcName)){
$fx = new ReflectionFunction($funcName);
foreach ($fx->getParameters() as $param){
$attribute_names[$param->name] = NULL;
if ($param->isOptional()){
$attribute_names[$param->name] = $param->getDefaultValue();
}
}
}
return $attribute_names;
}
Useful for variable type validation.
#Tom Haigh, or do it more classy:
function getArguments( $funcName ) {
return array_map( function( $parameter ) { return $parameter->name; },
(new ReflectionFunction($funcName))->getParameters() );
}
// var_dump( getArguments('getArguments') );
func_get_args
function my($aaa, $bbb){
var_dump( func_get_args() );
}
my("something","something"); //result: array('aaa' => 'something', 'bbb' => 'something');
also, there exists another global functions: get_defined_vars(), that returns not only function, but all variables.

How to check if a certain part of the array exists in another array?

I have an two associative arrayes and I want to check if
$array1["foo"]["bar"]["baz"] exists in $array2["foo"]["bar"]["baz"]
The values doesn't matter, just the "path".
Does array_ intersect_ assoc do what I need?
If not how can I write one myself?
Try this:
<?php
function array_path_exists(&$array, $path, $separator = '/')
{
$a =& $array;
$paths = explode($separator, $path);
$i = 0;
foreach ($paths as $p) {
if (isset($a[$p])) {
if ($i == count($paths) - 1) {
return TRUE;
}
elseif(is_array($a[$p])) {
$a =& $a[$p];
}
else {
return FALSE;
}
}
else {
return FALSE;
}
$i++;
}
}
// Test
$test = array(
'foo' => array(
'bar' => array(
'baz' => 1
)
),
'bar' => 1
);
echo array_path_exists($test, 'foo/bar/baz');
?>
If you only need to check if the keys exist you could use a simple if statement.
<?php
if (isset($array1["foo"]["bar"]["baz"]) && isset($array2["foo"]["bar"]["baz"]
)) {
//exists
}

Categories