In JavaScript nested functions are very useful: closures, private methods and what have you..
What are nested PHP functions for? Does anyone use them and what for?
Here's a small investigation I did
<?php
function outer( $msg ) {
function inner( $msg ) {
echo 'inner: '.$msg.' ';
}
echo 'outer: '.$msg.' ';
inner( $msg );
}
inner( 'test1' ); // Fatal error: Call to undefined function inner()
outer( 'test2' ); // outer: test2 inner: test2
inner( 'test3' ); // inner: test3
outer( 'test4' ); // Fatal error: Cannot redeclare inner()
If you are using PHP 5.3 you can get more JavaScript-like behaviour with an anonymous function:
<?php
function outer() {
$inner=function() {
echo "test\n";
};
$inner();
}
outer();
outer();
inner(); //PHP Fatal error: Call to undefined function inner()
$inner(); //PHP Fatal error: Function name must be a string
?>
Output:
test
test
There is none basically. I've always treated this as a side effect of the parser.
Eran Galperin is mistaken in thinking that these functions are somehow private. They are simply undeclared until outer() is run. They are also not privately scoped; they do pollute the global scope, albeit delayed. And as a callback, the outer callback could still only be called once. I still don't see how it's helpful to apply it on an array, which very likely calls the alias more than once.
The only 'real world' example I could dig up is this, which can only run once, and could be rewritten cleaner, IMO.
The only use I can think of, is for modules to call a [name]_include method, which sets several nested methods in the global space, combined with
if (!function_exists ('somefunc')) {
function somefunc() { }
}
checks.
PHP's OOP would obviously be a better choice :)
[Rewritten according to the comment by #PierredeLESPINAY.]
It's not just a side-effect at all, but actually a very useful feature for dynamically modifying the logic of your program. It's from the procedural PHP days, but can come in handy with OO architectures too, if you want to provide alternative implementations for certain standalone functions in the most straightforward way possible. (While OO is the better choice most of the time, it's an option, not a mandate, and some simple tasks don't need the extra cruft.)
For example, if you dynamically/conditionally load plugins from your framework, and want to make the life of the plugin authors super easy, you can provide default implementations for some critical functions the plugin didn't override:
<?php // Some framework module
function provide_defaults()
{
// Make sure a critical function exists:
if (!function_exists("tedious_plugin_callback"))
{
function tedious_plugin_callback()
{
// Complex code no plugin author ever bothers to customize... ;)
}
}
}
Functions defined within functions I can't see much use for but conditionally defined functions I can. For example:
if ($language == 'en') {
function cmp($a, $b) { /* sort by English word order */ }
} else if ($language == 'de') {
function cmp($a, $b) { /* sort by German word order; yes it's different */ }
} // etc
And then all your code needs to do is use the 'cmp' function in things like usort() calls so you don't litter language checks all over your code. Now I haven't done this but I can see arguments for doing it.
All the above being said, one might simply create a nested function to replace some localized, repetitive code within a function (that will only be used inside the parent function). An anonymous function is a perfect example of this.
Some might say just create private methods (or smaller code blocks) in a class, but that is muddying the waters when an ultra-specific task (which is exclusive to the parent) needs to be modularized, but not necessarily available to the rest of a class. The good news is if it turns out that you do need that function somewhere else, the fix is rather elementary (move the definition to a more central location).
Generally speaking, using JavaScript as the standard by which to evaluate other C based programming languages is a bad idea. JavaScript is definitely its own animal when compared to PHP, Python, Perl, C, C++, and Java. Of course, there are lots of general similarities, but the nitty, gritty details (reference JavaScript: The Definitive Guide, 6th Edition, Chapters 1-12), when paid attention to, make core JavaScript unique, beautiful, different, simple, and complex all at the same time. That's my two cents.
Just to be clear, I'm not saying nested functions are private. Just that nesting can help avoid clutter when something trivial needs to be modularized (and is only needed by the parent function).
All of my php is OO, but I do see a use for nested functions, particularly when your function is recursive and not necessarily an object. That is to say, it does not get called outside of the function it is nested in, but is recursive and subsequently needs to be a function.
There's little point in making a new method for the express use of a single other method. To me that's clumsy code and sort-of not the point of OO. If you're never going to call that function anywhere else, nest it.
In webservice calling we found it a much lower overhead (memory and speed) dynamically including in a nested fashion, individual functions over libraries full of 1000s of functions. The typical call stack might be between 5-10 calls deep only requiring linking a dozen 1-2kb files dynamically was better than including megabytes. This was done just by creating a small util function wrapping requires. The included functions become nested within the functions above the call stack. Consider it in contrast to classes full of 100s of functions that weren't required upon every webservice call but could also have used the inbuilt lazy loading features of php.
if you are in php 7 then see this:
This implementation will give you a clear idea about nested function.
Suppose we have three functions(too(), boo() and zoo()) nested in function foo().
boo() and zoo() have same named nested function xoo(). Now in this code I have commented out the rules of nested functions clearly.
function foo(){
echo 'foo() is called'.'<br>';
function too(){
echo 'foo()->too() is called'.'<br>';
}
function boo(){
echo 'foo()->boo() is called'.'<br>';
function xoo(){
echo 'foo()->boo()->xoo() is called'.'<br>';
}
function moo(){
echo 'foo()->boo()->moo() is called'.'<br>';
}
}
function zoo(){
echo 'foo()->zoo() is called'.'<br>';
function xoo(){ //same name as used in boo()->xoo();
echo 'zoo()->xoo() is called'.'<br>';
}
#we can use same name for nested function more than once
#but we can not call more than one of the parent function
}
}
/****************************************************************
* TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
****************************************************************/
#xoo();//error: as we have to declare foo() first as xoo() is nested in foo()
function test1(){
echo '<b>test1:</b><br>';
foo(); //call foo()
too();
boo();
too(); // we can can a function twice
moo(); // moo() can be called as we have already called boo() and foo()
xoo(); // xoo() can be called as we have already called boo() and foo()
#zoo(); re-declaration error
//we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
}
function test2(){
echo '<b>test2:</b><br>';
foo(); //call foo()
too();
#moo();
//we can not call moo() as the parent function boo() is not yet called
zoo();
xoo();
#boo(); re-declaration error
//we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()
}
Now if we call test1() the output will be this:
test1:
foo() is called
foo()->too() is called
foo()->boo() is called
foo()->too() is called
foo()->boo()->moo() is called
foo()->boo()->xoo() is called
if we call test2() the output will be this:
test2:
foo() is called
foo()->too() is called
foo()->zoo() is called
zoo()->xoo() is called
But we cannot call both text1() and test2() at same time to avoid re-declaration error
For those that suggest that there is no practical use of nested functions. Yes they have use and this is an example.
Imagine that I have a file called my_file.php which is used to get an ajax result out of. But what if there are times that you don't want to get the result through ajax but you want to include it twice in the same page without conflicts?
Lets say ajax file my_file.php :
<?php
// my_file.php used for ajax
$ajax_json_in = 10;
function calculations($a, $b)
{ $result = $a + $b;
return $result;
}
$new_result = $ajax_json_in * calculations(1, 2);
$ajax_json_out = $new_result;
?>
Below example includes the above file twice without conflict. You may not want to ajax call it, because there are cases that you need to include it straight in the HTML.
<?php
// include the above file my_file.php instead of ajaxing it
function result1
{
$ajax_json_in = 20;
include("my_file.php");
return $ajax_json_out;
}
function result2
{
$ajax_json_in = 20;
include("my_file.php");
return $ajax_json_out;
}
?>
Including the file makes the file's functions nested. The file is used both for ajax calls and inline includes !!!
So there is use in real life of nested functions.
Have a nice day.
I know this is an old post but fwiw I use nested functions to give a neat and tidy approach to a recursive call when I only need the functionality locally - e.g. for building hierarchical objects etc (obviously you need to be careful the parent function is only called once):
function main() {
// Some code
function addChildren ($parentVar) {
// Do something
if ($needsGrandChildren) addChildren ($childVar);
}
addChildren ($mainVar); // This call must be below nested func
// Some more code
}
A point of note in php compared with JS for instance is that the call to the nested function needs to be made after, i.e. below, the function declaration (compared with JS where the function call can be anywhere within the parent function
I have only really used this characteristic when it was useful to execute a small recursive function inside a primary, more categorical function, but didn't want to move it to a different file because it was fundamental to the behavior of a primary process. I realize there are other "best practice" ways of doing this, but I want to make sure my devs see that function every time they look at my parser, it's likely what they should modify anyway...
Nested functions are useful in Memoization (caching function results to improve performance).
<?php
function foo($arg1, $arg2) {
$cacheKey = "foo($arg1, $arg2)";
if (! getCachedValue($cacheKey)) {
function _foo($arg1, $arg2) {
// whatever
return $result;
}
$result = _foo($arg1, $arg2);
setCachedValue($cacheKey, $result);
}
return getCachedValue($cacheKey);
}
?>
Nested functions are useful if you want the nested function to utilize a variable that was declared within the parent function.
<?php
ParentFunc();
function ParentFunc()
{
$var = 5;
function NestedFunc()
{
global $var;
$var = $var + 5;
return $var;
};
echo NestedFunc()."<br>";
echo NestedFunc()."<br>";
echo NestedFunc()."<br>";
}
?>
I'm having some troubles with some object oriented programming in PHP.
I basically have a function within a class, which displays some text:
public function text() {
echo 'text';
}
Now I want to store the function name in an arra,y so I can reference it later:
$functions = array('text_func' => 'text');
And in an other function I want to call the above function with the Array reference, so I did the following:
public function display() {
$this->functions['text_func']();
}
The result will be basically:
text();
My question is that, how is it possible to make this function run? (The correct way it should be look like: $this->text()). However I can't do something like this, because it gives me an error:
$this->$this->functions['text_func']();
Any idea or solution for my problem?
The error message you carefully ignore probably warns you that $this cannot be converted to string. That gives you a pretty good clue of what's going on.
(Long answer is that method names are strings. Since PHP is loosely typed, when it needs a string it'll try to convert whatever you feed it with into string. Your class lacks a __toString() method, thus the error.)
You probably want this:
$this->{$this->functions['text_func']}();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here's an example from PHP.net that should help:
<?php
class Foo
{
function Variable()
{
$name = 'Bar';
$this->$name(); // This calls the Bar() method
}
function Bar()
{
echo "This is Bar";
}
}
$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // This calls $foo->Variable()
?>
Source: http://www.php.net/manual/en/functions.variable-functions.php
You're confusing a lot of things. First of all, you can use the magic constants __METHOD__ and __CLASS__ to determine in which class type and method you are currently executing code.
Secondly, a callable in PHP is defined as either an array with an object instance or static class reference at index 0, and the method name at index 1, or since PHP 5.2 a fully qualified string such as MyClass::myFunction. You can only dynamically invoke functions stored as one of these types. You can use the type hint callable when passing them between functions.
$this does not contain a reference for itself, so you should try just
$this->display();
instead of
$this->$this->functions['text_func'](); // WRONG
This is somewhat a follow up to a previous question - but I've distilled the question down and have the "works" vs. "doesn't work" cases narrowed down much more precisely.
My Goal:
I have a class MyClass that has an instance variable myFunction. Upon creating a MyClass object (instantiating), the constructor assigns the instance variable myFunction with the result of a call to create_function (where the code and args come from a db call).
Once this object of type MyClass is created (and stored as an instance variable of another class elsewhere) I want to be able to call myFunction (the instance variable anonymous function) from "anywhere" that I have the MyClass object.
Experimental Cases -- below is my highly simplified test code to illustrate what works vs. what doesn't (i.e. when the expected functionality breaks)
class MyClass extends AnotherClass {
public $myFunction;
function __construct() {
$functionCode = 'echo "NyanNyanNyan";';
$this->myFunction();
/*Now the following code works as expected if put in here for testing*/
$anonFunc = $this->myFunction;
$anonFunc(); //This call works just fine (echos to page)!
/*And if i make this call, it works too! */
self::TestCallAnon();
}
public function TestCallAnon() {
$anonFunc2 = $this->myFunction;
$anonFunc2();
}
}
However, if I do the following (in another file, it errors saying undefined function () in... within the Apache error log.
//I'm using Yii framework, and this is getting the user
//objects instance variable 'myClass'.
$object = Yii::app()->user->myClass;
$object->TestCallAnon(); // **FAILS**
or
$func = $object->myFunction;
$func(); // ** ALSO FAILS **
In addition, several variations of calls to call_user_func and call_user_func_array don't work.
If anyone is able to offer any insight or help that would be great :).
Thanks in advance!
You can't pass references to functions around in PHP like you can in for instance JavaScript.
call_user_func has limited functionality. You can use it like so:
class MyClass {
function func() {}
static function func() {}
}
function myfunc() {}
$i = new MyClass();
call_user_func("myfunc", $args);
call_user_func(array($i, "func"), $args);
call_user_func(array(MyClass, "staticFunc"), $args);
I ended up solving this issue via a workaround that ended up being a better choice anyways.
In the end I ended up having a static class that had a method to randomly return one of the possible identifiers, and then another method which accepted that identifier to build the anonymous function upon each class.
Slightly less elegant than I would like but it ends up working well.
Thanks to everyone for your efforts.
Why would PHP allow nesting functions?
<?php
function foo() {
function bar() {
return "bar";
}
return "foo";
}
print foo();
print bar();
.. is valid PHP.
But:
Why would nesting be needed ever?
And even if so, why can I call bar from anywhere (and not, e.g. only withing foo(), or trough foo.bar() or such).
I ran into this today, because I forgot a closing bracket somewhere, and had one too many further down. The code was valid and no errors thrown; but it all started acting really weird. Functions not being declared, callbacks going berserk and so on.
Is this a feature, and if so, to what purpose? Or some idiosyncrasy?
ANSWER: commentor points out that this is a duplicate of What are php nested functions for.
Note that the order is important here; you cannot call bar() before calling foo() in your example. The logic here appears to be that the execution of foo() defines bar() and puts it in global scope, but it's not defined prior to the execution of foo(), because of the scoping.
The use here would be a primitive form of function overloading; you can have your bar() function perform different operations depending upon which version of foo() declares it, assuming of course that each different version of foo() indeed defines a bar() function.
In PHP you can define functions, run-time constants and even classes conditionally. This allows you to define different functions / constants / classes depending on the circumstances.
Simply example: Define the String\Length function depending on whether multibyte support is turned on or off in your application.
namespace String;
if (\MULTIBYTE_MODE) {
function Length($string) {
return strlen($string);
}
} else {
function Length($string) {
return mb_strlen($string);
}
}
Nested functions are only a special case of conditional function definition.
I know that you can call functions using variable names like this:
$foo = "bar";
function bar()
{
echo "test";
}
$foo(); // echos test
I am wondering if in a class, an actual function overrides that.
If I had this class:
class myClass{
public $test;
public function __construct()
{
$this->test = new myOtherClass;
}
public function test()
{
echo "foo";
}
}
Would both of these work correctly?
$obj->test(); // echo foo
$obj->test->method(); // access a method of myOtherClass
Edit: The original idea for this was that myOtherClass held a class with one main function that was accessed all the time, and a few other less accessed ones. I could use test() to link the main function to the class so there is less typing. But given the first answer I'll probably stick away from that.
I don't know PHP well enough to answer your question, but I spent several years maintaining products and would like to point out a serious difficulty with maintainability with this. Consider that you have the question as to whether this will even work properly. Now consider that the person maintaining your code will (a) have the same question as you and (b) probably not read the whole class (unless it's a very small class). And if you're changing $test from outside the class, it will be even more difficult to understand.
While this is an interesting question, especially from an academic point of view, it's a terrible practice from a maintenance point of view. Please use different variable names for different purposes; for example, use $otherClass for the pointer to the other class and test() for the test function and your maintainers (including yourself, if you maintain your own code) will curse at you less :)
PHP allows different symbols with the same name. Object properties and methods are totally different things in PHP, unlike JavaScript and some other languages:
// all of them work OK
define('SomeClass', 'SomeClass');
function SomeClass () {}
class SomeClass {}
This causes ugly problems in PHP 5.3:
$foo = new StdClass;
$foo->bar = function () {
return "bar";
};
$foo->bar(); // does not work, unfortunately :(
You wrote:
$obj->test(); // echo foo
$obj->test->method(); // access a method of myOtherClass
Right, this is how it works. You're not using anything variable in there.
$obj->test; // member variable $test of $obj
$obj->test(); // method test() of $obj
$obj->$test(); // variable function, result depends on content of $test
$obj->test()->otherTest(); // invokes otherTest() on an object
// returned by $obj->test()
$foo = 'test';
$bar = 'otherTest';
$obj->$foo()->$bar(); // same as above, but please, for the love of God,
// don't ever use this. ;)