I'm trying to achieve almost similar things/properties of closure in PHP which is available in JS.
For example
function createGreeter($who) {
return function(){
function hello() use ($who) {
echo "Hi $who";
}
function bye() use($who){
echo "Bye $who";
}
};
}
I know my syntax is incorrect, this what I'm trying to achieve.
What I've done so far is.
function createGreeter() {
$hi = "hi how are you.";
$bye = "bye wish you luck.";
return function($operation) use ($hi, $bye){
if ($operation == "a") return $hi;
elseif ($operation == "b") return $bye;
};
}
$op = createGreeter();
echo $op("a"); #prints hi how are you.
echo $op("b"); #prints bye wish you luck.
Please look does PHP allows us to do this.
You could return an anonymous class which is created with the $who and then has methods which output the relevant message...
function createGreeter($who) {
return new class($who){
private $who;
public function __construct( $who ) {
$this->who = $who;
}
function hello() {
echo "Hi {$this->who}";
}
function bye(){
echo "Bye {$this->who}";
}
};
}
$op = createGreeter("me");
echo $op->hello(); // Hi me
echo $op->bye(); // Bye me
Decided to post as a new answer as it's a completely different solution. This follow the idea of creating private methods using closures (as linked to by OP in comment to my other answer - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Emulating_private_methods_with_closures).
This also draws on deceeze's comments on the original question, but casting the array to an object to more closely reflect the reference as being an object rather than an array...
function createGreeter($who) {
return (object)
[ "Hello" => function() use ($who) {
echo "Hello {$who}";
},
"Goodbye" => function() use ($who) {
echo "Goodbye {$who}";
}];
}
$op = createGreeter("me");
($op->Hello)();
($op->Goodbye)();
The ()'s around the methods are needed as it is a closure and not an actual method.
This gives...
Hello meGoodbye me
Related
I have a string variable
$worker_name = "video_convert"
I want to write a function with the name like the following
function video_convert(){
}
How can I do this in PHP? I tried
function eval($worker_name){
}
or
eval($worker_name) = function(){
}
But, it seems like it is not the correct way to do it in PHP.
You can do it as
$worker_name = 'video_convert';
$$worker_name = function() {
echo 'hi';
};
$$worker_name();
You could use call_user_func :
$worker_name ="video_convert"
function video_convert($text){
echo "Hello $text\n";
}
call_user_func($worker_name, 'World');
OR you could use the way you tried:
$worker_name = 'video_convert';
function video_convert(){
echo __METHOD__;
}
$worker_name();
OR like this:
$worker_name = function($text)
{
echo 'Anonymous function call '.$text
};
$worker_name('Hello');
PHP is flexible.
You can do somewhat like as
$worker_name = "video_convert";
function video_convert(){
echo "I've called a function using variable";
}
$worker_name();
If you want to use eval() function then use it by below way:-
$worker_name = "video_convert()";
function video_convert(){
echo "Called";
}
eval("$worker_name;");
I'm working with a third-party class, and I need to be able to run a section of code one of two ways, depending...
$reader->get()->first()->each(function($obj)
{
// Do stuff
}
OR
$reader->get()->each(function($obj)
{
// Do stuff
}
I've always been able to call properties variably with something like...
$a = 1;
$obj->{"$a"}
But unfortunately the below doesn't work...
if (some scenario)
{
$a = "get()->first()";
}
else
{
$a = "get()";
}
$reader->{"$a"}->each(function($obj)
My problem is i'm not sure how to phrase the question for google...I'm assuming there's a solution for the above problem.
Thanks in advance for any help!
You can only use ->{$variable} for the names of properties and methods of the class itself, you can't put PHP syntax like -> in there. What you can do is use function variables:
function get_all($reader) {
return $reader->get();
}
function get_first($reader) {
return $reader->get()->first();
}
$a = 'get_all'; // or $a = 'get_first';
$a($reader)->each(function($obj) {
// do stuff
});
Alternative to Barmar's answer, which imho is a bit clearer.
$it = function($obj) {
// do stuff
});
if (some_scenario) {
$reader->get()->first()->each($it);
} else {
$reader->get()->each($it);
}
One more solution:
if (some_scenario) {
$foo = $reader->get()->first();
} else {
$foo = $reader->get();
}
$foo->each(function($obj) {
// do stuff
});
Is there a trick in PHP 4 to implement functions which return functions? I expected that the following code would work:
function xxx($a) {
return function($b) {
print "a=$a, b=$b \n";
}
}
$f1 = xxx(1);
$f1(2);
Unfortunately, no luck in PHP 4. Probably it works in PHP 5, but I limited to PHP 4.
I tried to workaround with OO, but again failed (class declarations may not be nested):
class Closure {
function run($a) {
print "raise: NotImplementedException, instead: $a\n";
}
}
class WantCheckNesting extends Closure {
function run($a, $b) {
class Nested extends Closure {
function run($c) {
print "a=$a, b=$b, c=$c\n";
}
}
$o = new Nested();
return $o;
}
}
$d = new WantCheckNesting();
$e = $d->run(2, 3);
$e->run(4);
There is a function "create_function", but it is very limited: the body must be a string.
Any other ideas?
You're probably barking at the wrong tree. PHP is not a functional programming language. Some changes have been made starting with PHP 5.3, but even there you don't have your expected variable scopes that would allow you to do what you have in your examples.
The only tools you can use in PHP 4 are create_function and some ingenuity to write the function definition as a string.
<?php
function getMyFunc($a){
return create_function('$b', 'print "a='.$a.', b=$b";');
}
$f1 = getMyFunc(1);
$f1(2);
?>
...but even if this is simple for your posted example, it definitely isn't practical for more complex situations.
In PHP4 you can use Variable Functions like this, provided your function is already defined in the scope (so not a real closure).
THIS IS DIRTY CODE.
THIS IS NOT MUCH TESTED.
THIS IS NOT FAST (even slower than closures if that is possible).
It is just for fun and proving it "somehow" can be done if you really really need it.
Requires a writable tmp/ directory.
<?php
function xxx($a) {
$sid = GetUniversalSessionId();
$tmpfname= 'tmp/'.$sid.'.php';
$handle = fopen($tmpfname, "w");
fwrite($handle, '<?php
function func_'.($sid).'($b) {
$a='."'".str_replace("\'","\\'",str_replace("\\","\\\\",$a))."'".';
print "a=$a, b=$b \n";
}
?>');
fclose($handle);
include($tmpfname);
unlink($tmpfname);
return 'func_'.($sid);
}
$result=xxx(32);
$result(20);
// This is just to get a unique identifier for every connection and every function call:
// UNIVERSALSESSIONIDS v1.3
if(defined('UNIVERSALSESSIONIDS')) return;
define('UNIVERSALSESSIONIDS', TRUE);
function GetTimeStart() {
return strtotime('2006-07-10');
}
function GetUniversalSessionId() {
return GetCodedSid(letterNumBase(),16);
}
function GetCodedSid($baseChars,$Pad=0) {
$Zero=$baseChars{0};
list ($usec, $sec) = explode (' ', microtime());
$new_sid = ($sec-GetTimeStart()) . str_pad ((int)($usec * 100000000), 8, '0', STR_PAD_LEFT) . str_pad (rand (0, 9999), 4, '0', STR_PAD_LEFT);
$new_sid=ConvertDecToAnyStr($new_sid,$baseChars);
$new_sid=str_pad ($new_sid, $Pad, $Zero, STR_PAD_LEFT);
return $new_sid;
}
function divide($decstr,$decnum) {
$Start='';
$Result='';
$WRITE=FALSE;
do {
$Start.=substr($decstr,0,1);
$decstr=substr($decstr,1);
$DecStart=intval($Start);
$Rest=$DecStart%$decnum;
$PartDiv=($DecStart-$Rest)/$decnum;
if($PartDiv>0) $WRITE=TRUE;
if($WRITE) $Result.=$PartDiv;
$Start=$Rest;
} while ($decstr!='');
if($Result=='') $Result='0';
return array($Result,$Rest);
}
function bigBase() {
global $gSavedBigBase;
if(isset($gSavedBigBase)) return $gSavedBigBase;
$BigBase='';
for($i=33;$i<=128;$i++) $BigBase.=chr($i);
$gSavedBigBase=$BigBase;
return $BigBase;
}
function letterNumBase() {
global $gSavedBigBase2;
if(isset($gSavedBigBase2)) return $gSavedBigBase2;
$BigBase='';
for($i=ord('0');$i<=ord('1');$i++) $BigBase.=chr($i);
for($i=ord('A');$i<=ord('Z');$i++) $BigBase.=chr($i);
$BigBase.='_';
// for($i=ord('a');$i<=ord('z');$i++) $BigBase.=chr($i);
$gSavedBigBase2=$BigBase;
return $BigBase;
}
function ConvertDecToAny($decstr,$decbase) {
$Result=array();
do {
$Div=divide($decstr,$decbase);
$decstr=$Div[0];
$Rest=$Div[1];
$Result[]=$Rest;
} while($decstr!='0');
return $Result;
}
function ConvertDecToAnyStr($decstr,$baseChars='01') {
$decbase=strlen($baseChars);
$Result='';
do {
$Div=divide($decstr,$decbase);
$decstr=$Div[0];
$Rest=$Div[1];
$Result=$baseChars{$Rest}.$Result;
} while($decstr!='0');
return $Result;
}
?>
So I thought this should be easy, but, I'm struggling here...
Here's my code:
function xy() {
$array['var1'] = x;
$array['var2'] = y;
echo $this->_z;
}
function _z($array) {
$xy = $x.$y;
return $xy;
}
So, why doesn't that seemingly simple code work? I know with views you can pass arrays and the variables are accessible in the views with just their array title, but, why doesn't it work in this case?
Because function _z is not a view. Call it with $this->_z($array);. Also views are processed by CodeIgniter and variables passed into them. This doesn't work the same way for non-views. PHP won't do that automatically for you.
To load a view make a view file in /system/application/views/ and call it with $this->load->view('my_view_name', $array);
I would rewrite your functions as follows:
function xy()
{
$x = "some value";
$y = "some other value";
echo $this->_z($x, $y);
}
function _z($a, $b)
{
return $a.$b;
}
You can mimic the CI views behavior you want with the PHP native function extract() (That is how CI does it)
function xy() {
$some_array = array(
'foo' => 'Hello',
'bar' => 'world'
);
echo $this->_z($some_array);
}
function _z($array) {
extract ($array);
$xy = "$foo $bar";
return $xy;
}
xy();
Reference: http://php.net/manual/en/function.extract.php
One of the best explanation about accessing array from a function to a private function. thanks the code helped me
function _normal()
{
$arrayVariable = "value you want to pass";
echo $this->_toPrivateFuction($arrayVariable);
}
function _toPrivateFuction($arrayVariable)
{
// or print to check if you have the desired result
print_r(arrayVariable);
// if yes then you are ready to go!
return $arrayVariable;
}
I'm sure there's a very easy explanation for this. What is the difference between this:
function barber($type){
echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
... and this (and what are the benefits?):
function barber($type){
echo "You wanted a $type haircut, no problem\n";
}
barber('mushroom');
barber('shave');
Always use the actual function name when you know it.
call_user_func is for calling functions whose name you don't know ahead of time but it is much less efficient since the program has to lookup the function at runtime.
Although you can call variable function names this way:
function printIt($str) { print($str); }
$funcname = 'printIt';
$funcname('Hello world!');
there are cases where you don't know how many arguments you're passing. Consider the following:
function someFunc() {
$args = func_get_args();
// do something
}
call_user_func_array('someFunc',array('one','two','three'));
It's also handy for calling static and object methods, respectively:
call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);
the call_user_func option is there so you can do things like:
$dynamicFunctionName = "barber";
call_user_func($dynamicFunctionName, 'mushroom');
where the dynamicFunctionName string could be more exciting and generated at run-time. You shouldn't use call_user_func unless you have to, because it is slower.
With PHP 7 you can use the nicer variable-function syntax everywhere. It works with static/instance functions, and it can take an array of parameters. More info at https://trowski.com/2015/06/20/php-callable-paradox
$ret = $callable(...$params);
I imagine it is useful for calling a function that you don't know the name of in advance...
Something like:
switch($value):
{
case 7:
$func = 'run';
break;
default:
$func = 'stop';
break;
}
call_user_func($func, 'stuff');
There are no benefits to call it like that, the word user mean it is for multiple user, it is useful to create modification without editing in core engine.
it used by wordpress to call user function in plugins
<?php
/* main.php */
require("core.php");
require("my_plugin.php");
the_content(); // "Hello I live in Tasikmalaya"
...
<?php
/* core.php */
$listFunc = array();
$content = "Hello I live in ###";
function add_filter($fName, $funct)
{
global $listFunc;
$listFunc[$fName] = $funct;
}
function apply_filter($funct, $content)
{
global $listFunc;
foreach ($listFunc as $key => $value)
{
if ($key == $funct and is_callable($listFunc[$key]))
{
$content = call_user_func($listFunc[$key], $content);
}
}
echo $content;
}
function the_content()
{
global $content;
$content = apply_filter('the_content', $content);
echo $content;
}
....
<?php
/* my_plugin.php */
function changeMyLocation($content){
return str_replace('###', 'Tasikmalaya', $content);
}
add_filter('the_content', 'changeMyLocation');
in your first example you're using function name which is a string. it might come from outside or be determined on the fly. that is, you don't know what function will need to be run at the moment of the code creation.
When using namespaces, call_user_func() is the only way to run a function you don't know the name of beforehand, for example:
$function = '\Utilities\SearchTools::getCurrency';
call_user_func($function,'USA');
If all your functions were in the same namespace, then it wouldn't be such an issue, as you could use something like this:
$function = 'getCurrency';
$function('USA');
Edit:
Following #Jannis saying that I'm wrong I did a little more testing, and wasn't having much luck:
<?php
namespace Foo {
class Bar {
public static function getBar() {
return 'Bar';
}
}
echo "<h1>Bar: ".\Foo\Bar::getBar()."</h1>";
// outputs 'Bar: Bar'
$function = '\Foo\Bar::getBar';
echo "<h1>Bar: ".$function()."</h1>";
// outputs 'Fatal error: Call to undefined function \Foo\Bar::getBar()'
$function = '\Foo\Bar\getBar';
echo "<h1>Bar: ".$function()."</h1>";
// outputs 'Fatal error: Call to undefined function \foo\Bar\getBar()'
}
You can see the output results here: https://3v4l.org/iBERh it seems the second method works for PHP 7 onwards, but not PHP 5.6.