Can you declare a function like this...
function ihatefooexamples(){
return "boo-foo!";
};
And then redeclare it somewhat like this...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
Is it possible to overwrite a function that way?
Any way?
Edit
To address comments that this answer doesn't directly address the
original question. If you got here from a Google Search, start here
There is a function available called override_function that actually fits the bill. However, given that this function is part of The Advanced PHP Debugger extension, it's hard to make an argument that override_function() is intended for production use. Therefore, I would say "No", it is not possible to overwrite a function with the intent that the original questioner had in mind.
Original Answer
This is where you should take advantage of OOP, specifically polymorphism.
interface Fooable
{
public function ihatefooexamples();
}
class Foo implements Fooable
{
public function ihatefooexamples()
{
return "boo-foo!";
}
}
class FooBar implements Fooable
{
public function ihatefooexamples()
{
return "really boo-foo";
}
}
$foo = new Foo();
if (10 == $_GET['foolevel']) {
$foo = new FooBar();
}
echo $foo->ihatefooexamples();
Monkey patch in namespace php >= 5.3
A less evasive method than modifying the interpreter is the monkey patch.
Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own.
Ninja skills
Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces.
Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. As this topic, fallback to global functions, aims to explain.
If you don't provide a namespace when calling a function, PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. For our example if you are calling print_r(); from namespace My\Awesome\Namespace; What PHP does is to first look for a function called My\Awesome\Namespace\print_r(); then My\Awesome\print_r(); then My\print_r(); until it finds the PHP built in function in the global namespace \print_r();.
You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists.
Expect a fatal error to the likes of:
Fatal error: Cannot redeclare print_r()
But nothing stops you, however, from doing just that within the scope of a namespace.
Patching the monkey
Say you have a script using several print_r(); calls.
Example:
<?php
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
But you later change your mind and you want the output wrapped in <pre></pre> tags instead. Ever happened to you?
Before you go and change every call to print_r(); consider monkey patching instead.
Example:
<?php
namespace MyNamespace {
function print_r($object)
{
echo "<pre>", \print_r($object, true), "</pre>";
}
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
}
Your script will now be using MyNamespace\print_r(); instead of the global \print_r();
Works great for mocking unit tests.
nJoy!
Have a look at override_function to override the functions.
override_function — Overrides built-in
functions
Example:
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
short answer is no, you can't overwrite a function once its in the PHP function scope.
your best of using anonymous functions like so
$ihatefooexamples = function()
{
return "boo-foo!";
}
//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
return "really boo-foo";
}
http://php.net/manual/en/functions.anonymous.php
You cannot redeclare any functions in PHP. You can, however, override them. Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want.
So, keep in mind that when you override a function, you lose it. You may want to consider keeping it, but in a different name. Just saying.
Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function.
Example:
rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
I would include all functions of one case in an include file, and the others in another include.
For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really }
It helps the readability / maintenance of your program, having all functions of the same kind in the same inc.
Then at the top of your main module
if ($_GET['foolevel'] == 10) {
include "really.inc";
}
else {
include "simple.inc";
}
You could use the PECL extension
runkit_function_redefine — Replace a function definition with a new implementation
but that is bad practise in my opinion. You are using functions, but check out the Decorator design pattern. Can borrow the basic idea from it.
No this will be a problem.
PHP Variable Functions
Depending on situation where you need this, maybe you can use anonymous functions like this:
$greet = function($name)
{
echo('Hello ' . $name);
};
$greet('World');
...then you can set new function to the given variable any time
A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file):
Main File:
<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>
Include File A:
<?php
if (!#$Override) {
function F1 () {echo "This is F1() in A";}
}
?>
Include File B:
<?php
function F1 () {echo "This is F1() in B";}
?>
Browsing to the main file displays "This is F1() in B".
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 have a scenario where I'm trying to incorporate several people's PHP work, some of it OOP and some not. I want to pull a library file of functions into a class and have those functions be available to other files that reference the class. I know I can just call the library functions directly, but then I would have to update all of the dependent files to do likewise. Example:
class do_something {
function test_state() {
...
}
if ($this->test_state($var)) {
...
}
}
Where test_state() is identical to the same-named function in the library file, making for redundant code to keep sync'd. That can be changed to:
class do_something {
if (test_state($var)) {
...
}
}
But that creates the aforementioned problem of $this->test_state() not being available to files dependent on the class. What I'd like to be able to do is something like:
class do_something {
public function test_state() = test_state();
if ($this->test_state($var)) {
...
}
}
Obviously, that's a very rough and incorrect example of what I'm trying to do... Is there any way in OOP to make that sort of reassignment, making the method of the same name as the function available within the class?
You can use a workaround to simulate this. In fact you would often want this approach to bolt on closures to objects in PHP. It leverages the magic __call method in PHP to redirect method calls to ordinary functions (beware: no $this available).
class do_something {
function __call($func, $args) {
if (isset($this->$func) && is_callable($this->$func)) {
return call_user_func_array($this->$func, $args);
}
}
}
Then you can "register" functions that you want to allow (or closures) with a simple assignment:
$do_something->function_name = "global_function_name";
$do_something->or_even = array("other_class", "method");
But again, this doesn't make them proper methods as such.
You'd create your base utility class, then extend it. See PHP's manual entry for inheritance for the details. I'm not saying this is the best solution for your exact situation, but I think it answers the question you were trying to get at.
What you're asking for isn't possible directly, but can be faked with a quick (horrible) hack:
class do_something {
public function test_state($param) {
return test_state($param);
}
...
$this->test_state($param);
...
}
Good luck with refactoring!
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! ;-)
I'm making a plugin system. I have a class extensionmanager that takes the name of a plugin as a constructor parameter. Long story short, this is the code I'm trying to run:
$this->parsedata = function($data) {
$this->extension::parsedata($data);
};
$this-extension is a string with the name of the plugin. I have run static functions in the exact way shown in this example before. Now I'm getting the error unexpected T_PAAMAYIM_NEKUDOTAYIM on that second line (I've heard it roughly translates to "unexpected double colon")
Could anyone help me understand why?
Before the above example I tried to run something like this
$this->parsedata = &$this->extension::parsedata;
Hence the question title. The top example I thought was closer to working so I changed it.
call_user_func may give you a solution. Somewhere in the examples you have this code :
<?php
namespace Foobar;
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0
?>
I think you can easily adapt this to call your static function. For example something like :
call_user_func(array($this->extension, 'parseData'), $data);
Do that:
$self = $this;
$this->parsedata = function($data) use ($self) {
{$self->extension}::parsedata($data);
};
Yet, I would suggest to avoid static functions. After all, whoever is going to use your extension manager will need to conform to some interface. Why not take advantage of abstract methods or interfaces to make the user conform to your interface?
Current situation:
I have the current version of my MVC Framework which uses classes as controllers.
I have some "vintage" modules from my old MVC Framework which uses simple, flat includes as controllers.
Much simplified that means:
New Version:
<?PHP
class blaController extends baseController {
private $intVar;
function dosomethingFunction() {
$this->intVar = 123;
$this->view('myView');
}
}
?>
Old Version:
<?PHP
$globalVar = 123;
// view "controllername" is automatically shown
?>
I'm now trying to write a wrapper to be able to use my old controllers in my new MVC without having to rewrite everything. To do so, I have a "wrapper" controller:
class wrapController extends baseController {
function dosomethingFunction() {
require 'old_dosomething.function.php';
$this->view('old_dosomething_view');
}
}
(Once again: This is VERY, VERY simplified - just to get the idea over. Not actual code.)
The problem with that approach is, that the previously global variable $globalVar now only exists inside of the method "dosomethingFunction" and cannot be accessed by the view.
This wouldn't be the case if I could force the require to behave as "in global scope" so that $globalVar would once again be available in global scope.
So: Is there some way to achieve "require_global" or something similar?
(One solution for my problem would be to modify my old controllers to start with a bunch of "global" commands, but I'd prefer a solution where I don't have to change so much of that old code.)
(Note: Please don't tell me that GLOBALS are bad. It totally misses the point of this question. Just accept that it is a requirement to keep some old code working in a newer, cleaner environment.)
You can add local variables defined within dosomethingFunction() to global scope:
class wrapController extends baseController {
function dosomethingFunction() {
require 'old_dosomething.function.php';
//begin added code
$vararr = get_defined_vars();
foreach($vararr as $varName => $varValue)
$GLOBALS[$varName] = $varValue;
//end added code
$this->view('old_dosomething_view');
}
}
Note, that for this to work as expected, you should call require before using any other thing in the function. get_defined_vars() returns only variables from the current scope, so no array_diff hacks are needed.
This is the easiest solution I can think of.
Use the get_defined_vars() function twice and get a diff of each call to determine what variables were introduced by the required file.
Example:
$__defined_vars = get_defined_vars();
require('old_dosomething.function.php');
$__newly_defined_vars = array_diff_assoc($__defined_vars, get_defined_vars());
$GLOBALS = array_merge($GLOBALS, $__newly_defined_vars);
$this->view('old_dosomething_view');
Hmmm, this is an issue I've never before seen. I suppose you could do this
class wrapController extends baseController {
function dosomethingFunction() {
require 'old_dosomething.function.php';
// Force "old" globals into global scope
$GLOBALS['globalVar'] = $globalVar;
$this->view('old_dosomething_view');
}
}
But that's a pretty tedious, manual process as well, depending on how many globals we're talking about. I'll think about this, but I don't know of any "auto-magic" solution off the top of my head.
For anybody interested: My (so far) final version:
class wrapController extends baseController {
function dosomethingFunction() {
// ... do some initialisation stuff ...
$__defined_vars = array_keys(get_defined_vars());
require 'old_dosomething.function.php';
$__newly_defined_vars = array_diff(
array_keys(get_defined_vars()),
$__defined_vars,
array('__defined_vars')
);
foreach ($__newly_defined_vars as $var) {
$GLOBALS[$var] = &$$var;
}
$this->view('old_dosomething_view');
}
}
Ugly, but it works. Thanks for all your great help!
Have you tried Zend_Registry from Zend Framework?
The registry is a container for storing objects and values in the application space. By storing the value in the registry, the same object is always available throughout your application. This mechanism is an alternative to using global storage.
http://framework.zend.com/manual/en/zend.registry.html