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.
Related
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 posting this because it wasn't readily apparent on Google or php.net
==> Please demonstrate several examples of the syntax for forward declaring functions, in the PHP language.
For example (in C++):
int foo(); // forward declaration
int x = foo(); // calling the function.
int foo() // the actual implementation
{
return 5;
}
How would this look in PHP? How about with multiple arguments? How about with default arguments? What are the best practices and why?
You don't need to do forward declaration in PHP, instead you need to have the function declared, in current script (even if it's after the invocation), or in any included/required script, givent that the include/require statement is executed before you call the function.
There's no forward declaration.
If on the current script, even at the end, after the invocation: it' ok
If it's on a script INCLUDEd/REQUIREd by the current script, the INCLUDE/REQUIRE statement should have been executed BEFORE invocation of the function.
If it's on a script that INCLUDE/REQUIRE the current script: it's ok (even if declared AFTER the INCLUDE/REQUIRE statement)
I'd say the requested example is not the best for demonstrating the need of forward declarations. Say, we need the following instead:
function foo($n) {
echo 'Foo';
if($n>0) bar($n-1);
}
function bar($n) {
echo 'Bar';
if($n>0) foo($n-1);
}
foo(200);
The code above works perfectly in PHP despite of "undefined" function bar inside foo. It appears that PHP checks function definition when it is called.
So the answer is:
PHP doesn't have forward declarations.
The function doesn't have to
be defined before it appears in the text, but it must be defined
before it is called.
Would it not just be...
$x = foo();
function foo() {
return 5;
}
echo $x; //echos "5"
?
PHP does not do forward function declarations (or "function prototyping*). The closest thing we have is Object Interfaces and Abstract Methods. These are called "method prototypes" or "method declarations" (declaration as opposed to definition, which carries a c-style semantic)
Interface MyWidgetInterface {
function calculateThings(SomeClass $foo);
}
Abstract Class MyAbsClass {
public abstract function sayHello();
}
Class MyObj Extends MyAbsClass Implements MyWidgetInterface {
public function calculateThings(SomeClass $foo) {
}
public function sayHello() {
echo "Hi!\n";
}
}
$thing = new MyObj();
$thing->sayHello();
One of the reasons we don't have/need forward declared functions is that php parses your script before it compiles it, every time. It finds your functions before it starts executing the file, so it knows they are there. In fact, I can't remember how far back you'd have to go to even have to have defined the function before calling it. I've been doing PHP for 9 years and it's never needed that :-)
If you want that a function to return a certain type value in PHP, you can use something like this.
function foo($param) {
// code
return (int) $param; // or (string), (float)
}
Or, when you access the function:
$x = (int) foo($param);
Referring to the default argument you can do like this
function foo( $param1="value1" , $param2="value2" ){
echo $param1." ".$param2;
}
foo();
foo("not default","not default");
foo(NULL,"not default");
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
nested functions in php throws an exception when the outer is called more than once
why does
function foo(){
function bar(){
}
}
bar();
return fatal error on nonexistent function bar
while
function foo(){
function bar(){
}
}
foo();
foo();
gives fatal error on duplicate declaration for bar()?
does php handle the function as global or in the parent's function scope?
The function itself is defined at global scope, even if it was defined inside another function. In the first case, if you don't call foo() before bar(), bar() will not yet exist.
You can test with function_exists() before creating it:
function foo(){
// Don't redefine bar() if it is already defined
if (!function_exists("bar")) {
function bar(){
}
}
}
However, since the nested function is not scoped to the outer function, the use cases for defining a function inside another function are somewhat limited. Furthermore, it introduces some odd side-effects into your code which can become difficult to understand and maintain. Consider if you really want to do this, and rethink your reason for doing so if necessary. You might be better served by namespaces or classes/objects if what you're looking for is scope limits.
Functions are always created in the global scope, but only when their definition is executed.
The function "inside" is only declared when the outer function is called.
In your first example, you don't call foo(), therefore bar() is never declared.
In your second example, you call foo() twice, so bar() is declared twice.
In the first example, bar is declared in the function foo. So calling bar makes no sense without first calling foo since its definition hasn't been executed yet. In the second example, you are calling foo twice so the bar function gets declared twice.
In Python you can have the following:
def foo(param1, param2):
def bar():
print param1 + param2
bar()
I am having some difficulties with this behaviour in PHP though.
I expect this to work in the following way:
function foo($param1, $param2)
{
function bar()
{
echo $param1 + $param2;
}
bar();
}
But that fails. So I read some about closures (this is called a closure is it not? It is in Python, that I know). And in the php documentation about anonymous functions (which they said to have been implemented as closures) they tell you to use the use() expression in the following manner:
function foo($param1, $param2)
{
function bar() use($param1, $param2)
{
echo $param1 + $param2;
}
bar();
}
But that still fails. So I changed it to the PHP-anonymous function a-like like this:
function foo($param1, $param2)
{
$bar = function() use($param1, $param2)
{
echo $param1 + $param2;
};
$bar();
}
That does work, however it just looks really ugly. Am I missing something? Can I improve this in any way? Or will I just have to use the 'ugly' way?
(I am not looking for a discussion about if closures are useful)
I couldn't find the function bar() use($param1, $param2) syntax on the manual page you linked to, just the "ugly" version that works (which is truly anonymous). I guess you'll have to use that.
On your second example, bar is not a closure. To create a closure in PHP you have to use the ugly use, or the Closure class. Every function will create its own local scope, but closures are not automatic.
PHP seems to have an odd definition for the term "closure", as you probably noted when you read the manual. They define it as a synonym for "anonymous function":
Anonymous functions, also known as closures (...)
Confusing, right? Later, they explain you need the use keyword if you want to inherit the parent scope:
Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header.
The PHP Wiki rfc page on closures gives us some hints on why closures were implemented this way:
PHP's notion of scope is quite different than the notion of scope other languages define. Combine this with variable variables ($$var) and it becomes clear that automatically detecting which variables from the outer scope are referenced inside are closure is impossible. Also, since for example global variables are not visible inside functions either by default, automatically making the parent scope available would break with the current language concept PHP follows.
In PHP, you can't access intermediate scopes. You only have your local scope, and the global scope. This is an artefact of the perverse scope rules of PHP, which are the complete opposite of any sane language's scope rules.
In PHP, a named function declaration (function bar ()) declares a function in the global scope. So in your first example, when you run your foo function, it will define a bar function in the global scope, and then everybody can access the bar function as if you declared it outside of foo. Functions and variables are separate in PHP. There is just one scope for named functions: global; whereas you have local variables, there is no such thing as locally-scoped functions.
In other words, putting it inside of foo is an illusion; named function declaration always declares it globally; putting it inside foo simply delays the time when the declaration is run (thus delaying when it is defined) to the execution of foo.
A closure is what you need. Other answers have showed you how to do that.
can I put a function in PHP inside a if structure? like this:
<?php
if(true){
function HelloWorld(){
echo "Hello World!!!";
}
HelloWorld();
}
?>
because I have tried and it works, but I don't know if it is correct or not. Thanks
This is perfectly legal - it simply defines the function within the if statement block. That said, quite why you'd want to do this is somewhat of a mystery.
It's also worth noting that this function will be available in the global scope (i.e.: outside of the if statement block), as...
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.
See the PHP User-defined functions manual page for more information.
As middaparka says, this is perfectly legal, but in terms of using it, you might want to check if a function exists before declaring it:
if (!function_exists("foo"))
{
function foo()
{
return "bar";
}
}
function_exists documentation
It looks a bit strange, but yes it's legal
As of PHP 5.3 if you need a function with a limited scope (say for a callback) you can use anonymous functions / closures
I wanted to add an answer here, because there's a caveat that isn't addressed in the other answers.
Based on my testing in 5.3, it appears that functions that are defined inside if structures are defined at runtime, rather than at compile time like other functions.
For example, outside a conditional block, this:
foo();
function foo(){
echo 'foo!';
}
works fine because the function is defined at compile time, and executed at runtime. But calling the function before defining it while inside a condition block:
if(1){
foo(); // Call to undefined function!
function foo(){
echo 'foo!';
}
}
Will produce a call to undefined function error, at least as of version 5.3.
But defining the function in an if block before calling it is valid:
if(1){
function foo(){
echo 'foo!';
}
foo(); // No errors, since function is defined!
}
So there is a major gotcha to be aware of when defining functions inside a conditional: the function must be defined in the code before calling the function, since conditional functions don't seem to get defined at compile time.
The OP also asked about performance. If the conditional function is defined at runtime instead of compile time like most other functions, then this function will not benefit from performance boosters like OpCode caching, which depending on the circumstances, could slow down your application. For example, if your master php file looked like:
if($IsLoggedIn){
// include files/functions and bootstrap here...
}
Then the entire application might not benefit from OpCode caching at all.
Basically yes, according to the manual:
Any valid PHP code may appear inside a
function, even other functions and
class definitions.
Personally I haven't had a situation in which I'd actually do such a thing. Most of the time it would be easier to group your functions on a place where it actually can be found! ;-)