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>";
}
?>
If I have two functions like so:
function func1($arg){
function func2(){
}
}
Is there a way to use $arg inside the second function?
You can use the same argument inside the nested function, but I would not recommend doing it. It will get messy sooner. The best practice would be to define the function outside and then use it wherever you want. If the function does a task that's not repeated frequently, then why do you have a nested function in the first place? Place all the logic inside the first function itself and do whatever you need.
If you're using PHP 5.3+, you can make use of the Lambda functions. For example, to sum two input variables, it can be written as:
function some_func($a) {
return function($b) use ($a) {
return sum($a, $b);
}
}
If that's not an option and you're okay with nested functions and the problems that come from using it, then you can do the following:
function func1($arg) {
function func2($arg) {
# code...
}
}
If your function has to accept multiple parameters, then you might use func_get_args() and / or func_num_args().
This is not advised, try to keep your functions as small as possible / don't nest functions or too many statements. You also might need func2 elsewhere.
If you want the args for the 2nd function, you will have to pass them as parameters for the function; func2($arg). Would be stupid to globalize variables or save them in a session.
Yes. You need to separate your functions and if you want to call function 2 inside of function 1 you would do like so :
function func1($arg){
//write some code
func2($arg);
}
function func2($arg2){
//write some more code
}
I am modifying my PHP framework and trying to figure out an easier way to deal with different request types.
Currently I have this block in a controller method
$methodHandler = self::getMethodHandler(__FUNCTION__);
$this->$methodHandler();
Where getMethodHandler is
protected static function getMethodHandler($function) {
return $function."_".ucwords(strtolower(Request::getMethod()));
}
Ideally I want to reduce that two lines into one but PHP ain't having it
$this->self::getMethodHandler(__FUNCTION__)();
Anyway I could do this?
This should work:
$this->{self::getMethodHandler(__FUNCTION__)}();
That will evaluate self::getMethodHandler(__FUNCTION__) and call the result as a method of $this.
I have tested the following and it doesn't work. Is there a similar way of achieving this?
A compiling class which formulates a template:
private function include_header () {
function _metadata () {
// Metadata compiler
return $metadata;
}
include (path . "header.php");
}
header.php
<html>
<head>
<?php
_metadata ();
?>
<title>Hello Stackoverflow!</title>
</head>
<body>
...
The _metadata (); function is only available within the include_header (); function - nowhere else in the class. I don't want to have to write $this->_metadata (); in the template file only _metadata ();. Is that achievable?
Alternatively one could create an external file, for example functions.php which has the underscore functions specifically for the template - but I'd much rather see if the original query is possible.
Thank you in advance.
From the manual:
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
So, essentially, you can't do what you're trying to do. _metadata will always be a global function if it is defined with the function _metadata() { syntax. The normal function syntax only supports global functions.
However, PHP 5.3 introduces something called "anonymous functions". These can be assigned to a variable. Since variables can be scoped to a function scope (they are only global if you explicitly say so), you can limit them in this way.
For instance:
$_metadata = function() {
// Metadata compiler
return $metadata;
};
This could then be called in header.php with:
<?php $_metadata(); ?>
Note that this is less stable: it is, for instance, possible to redefine the variable to be a different anonymous function – or indeed not a function at all. The safest solution, ultimately, is to use a templating language that solves these issues for you. If not, you can either accept that you'll have to use global functions or anonymous functions.
You can't define nested function in PHP. I mean, you can, but there's no purpose since they'll have a global scope and therefore they will be callable from any point of the script.
But you actually don't need to define a _metadata() function, you can just execute all the function logic inside include_header() and then store everything in the variable $metadata, which will be printed in the include with a simple <?php echo $metadata; ?>.
If you really need to define a function you can use the function create_function() or (just for PHP > 5.3) an anonymous function. Since they will be encapsulated inside a variable, which has a function scope, they won't be available outside.
I'm using the Markdown library for PHP by Michel Fortin. Setup is easy and it works great like this:
include_once "markdown.php";
$my_html = Markdown($my_text);
However, I have a class in which I want to pass stuff and 'Markdown' it, like so:
class Test
{
public function showMarkdown ($text)
{
return Markdown($text);
}
}
Obviously, my class is much larger than this, but this is what it boils down to. In my main script I do:
include_once "markdown.php";
$test = new Test();
echo $test->showMarkdown($text);
This returns an error, saying the function 'Markdown' is undefined. That seems obvious, because it's not within the class and I haven't used a scope operator. But when I put the include inside my class and use $this->Markdown or self::Markdown the function is still undefined. I figured that the Markdown function can't be defined inside another function.
So, how can I solve this? I need to do the include, which loads the Markdown function (and the rest of its family) but I want to be able to use it from within my classes.
Thanks for your answers/ideas.
Your example code calls a free function called Markdown (which presumably is defined in markdown.php). You simply need to put the include in the same file as your Test class.
After doing this, you will still call Markdown as a free function, and not as an instance ($this->Markdown) or static (self::Markdown) method.
write
function showMarkdown ($text)
in place of
public function showMarkdown ($text)
and
echo $test->showMarkdown("Hello World");