This question already has answers here:
Redefining PHP function?
(9 answers)
Closed 8 years ago.
Can I redeclare a existing function, with the same name, but different code? Or somehow "disable" the old function?
I want to redefince a core WordPress function, but since plugins and theme call this function a lot, I need to keep the same function name.
You could use the WordPress hooks (called filters and actions) and then use the add_filter() function to override the function you are using.
i.e.
function function_name() {
//code goes here
}
$hook = 'get_options'; // the function name you're filtering
add_filter( $hook, 'function_name' );
The Codex will help a lot with this.
http://codex.wordpress.org/Plugin_API/Filter_Reference
Only if you use something like APD that extends the zend engine to allow for that:
Intro
Override Method Docs
Note: Runkit seems like a better option than APD since it's more specific to this purpose and would allow you to keep the original method intact at a different address.
You can wrap the block defining the original function in a conditional checking if another of the same name is not already defined (I'm assuming you mean Wordpress functions and not core PHP ones)
<?php
if(!function_exists('function_name')){
//old definition here
} ?>
You could then redefine it above while still preserving the original should you need to roll back to it.
Depending on how complex the changes are and how many times you may do this, you may also want to look into Namespaces if you are on PHP 5.
Just comment the old function out and write your new one ;)
In PHP it is not possible to redefine or overload (i.e. define a function with the same name but different parameters) a function natively. There though are extensions like runkit which allow to redefine functions (runkit_function_redefine), but you probably don't want to use these (such extensions are rarely installed and mostly unreliable.)
My attempted solution was to do this:
function suffusion_get_image($options = array()) {
include_once ABSPATH.'wp-content/themes/suffusion-child/functions/media.php';
return childtheme_overide_suffusion_get_image($options = array());
....
}
Obviously there is an overhead at upgrade as you would need to add lines back into the scripts again and I have used this method successfully to date but now trying to do it with get_terms in the wp-includes and hitting a redeclaration issue which I am trying to resolve or workaround at the moment.
My reason to edit core is that the existing core does not provide in a convenient way for a multisite requirement.
Someone has just suggested on another forum however using override_function but the manual is worded such that it appears to be of use only to built-in functions - I took it that means PHP built in functions
Related
Is there a way to catch method/function calls and return event with php like the xdebug trace?
I tried using the register_tick_function, but i'm not pretty sure this is the good approach.
I also tried to do my own php extension (using Zephir) but still the same problem.
Btw, I don't want to use xdebug extension. What is the best approach ?
The approach is to write a PHP extension that hooks into zend_execute and zend_execute_internal.
See the following related lines in the tideways_xhprof profiler extension:
https://github.com/tideways/php-xhprof-extension/blob/master/tideways_xhprof.c#L15-L18
These first two lines declare global variables to store the old / original function pointers into. The second two lines are the declaration of the new functions that wrap the original ones.
https://github.com/tideways/php-xhprof-extension/blob/master/tideways_xhprof.c#L67-L71
Now in module init, we can keep the reference of the old pointers and overwrite the one the Zend engine uses with our own functions.
https://github.com/tideways/php-xhprof-extension/blob/master/tideways_xhprof.c#L164-L200
These lines are the new implementations of the hooks. They call the original ones.
Xdebug does this in a similar way, but the code is much more complex, because it has many different features hooking into the function cycle.
Is there a way using function_exists that I could check that if for example if 'mysql_query' is called and therefore I can run some code via the if statement? to basically error it so that I can go and change it to PDO?
function_exists() is only for checking if a function is defined rather than if a function is being called.
However you can rename and override a PHP function to get the desired effect, using a wrapper as #wogsland mentioned in the comments. This method requires APD installed. For example:
<?php
// First rename existing function
rename_function('mysql_query', 'original_mysql_query');
// Override function with another
override_function('mysql_query', '$query', 'return override_mysql_query($query);');
// Create the other function
function override_mysql_query($query)
{
echo "Calling original_mysql_query($query)";
return original_mysql_query($query);
}
In php 7, mysql_* functions are deleted and you are then able to redefine them pointing them to their new functions, such as mysqli or PDO.
But to answer your question, you could also rename the internal functions in PHP explained in this page:
http://php.net/manual/en/function.runkit-function-rename.php
And create a user function with the same name as the function you're trying to call and let it do something else instead. But I would not recommend it.
As NoChecksum also stated, "rename_function" and "override_function" is also an option.
Why do we need to check function_exists for user defined functions? It looks ok for internal or core PHP functions but if user know and defined a function himself then why do need to check for its existance?
Below is custom user defined function
if( !function_exists( 'bia_register_menu' ) ) {
function bia_register_menu() {
register_nav_menu('primary-menu', __('Primary Menu'));
}
add_action('init', 'bia_register_menu');
}
Thanks
To make sure you don't register the same function twice, which will cause an error.
You also use if(function_exists('function_name')) when you are calling functions defined in plugins. In case you deactivated your plugin, your site will still be functional.
In dynamically loaded files using autoloaders, the file containing the function or class might not have loaded, so you need to check if it exists
This answer on the Wordpress StackExchange clarifies why you should sometimes use if function_exists around a function declaration in a theme:
The if function_exists approach allows for a child theme to override the function definition by simply defining the function themselves. Since child theme's functions.php files load first, then they will define the function first and the parent's definition will not get loaded.
I suppose it's analogous to the protected keyword in object oriented languages.
However I still wonder whether there would be any need for it around function declarations in plugins.
Imagine that you use you're URL to get the function name and call it.
Then we have the following info:
url: http://mysite.com/my/page/
When converting this url into a function name, you would do something like this:
implode('_', $myUrlPart); //my_page
The output would be "my_page" as string. But if you call this right away and the function does not exist, an error will be shown. This is where the function_exists comes in, take a look:
if (function_exists($function_name)) {
$function_name(); //the function is called
} else {
//call other function to show HTTP 404 page or something like that
}
Does this makes it a little clearer?
Because WordPress is designed so poorly it does not have any proper mechanism for autoloading modules like that, so you need to add safeguards.
My question is if it's possible to extend a declared function.
I want to extend mysql_function to add mysql query that insert into a table some logs : 'query' - the parameter of mysql_query, date,page...etc
My question is if it's possible to extend a declared function.
No.
You can extend a class method and call parent::methodname() to run the previous code (which is almost what you ask for), but for normal functions, there is no way to do this.
There are some esoteric PHP extensions that allow overriding functions, but I assume that's not what you need and their use is rarely practical.
What you probably want to do is create a new function, and call the existing function in it.
No, you cannot do that. Either enable the MySql Query Logs or wrap the code doing the queries into a Logging Decorator or use an abstraction like Zend_Db that can take a Profiler or use a transparent logging plugin for mysqlnd
You need to write a function that will take your query, log the sql first, runs your query, then return the results.
E.G
<?php
function mysql_query_log($sql)
{
mysql_query('insert into .... values ...');
$r = mysql_query($sql);
$results;
//do the normal thing you do with mysql here
return $results;
}
This is not extending a function though, you can only extend a class
It's not possible.
You should have created your own API (or use an existing one) to access the DB so when you need logging you can simply enhance your own API function. It also comes very handy if you need some custom error handling function. Refactor the code.
Well.. PHP says this: http://php.net/manual/en/function.override-function.php
from http://php.net/manual/en/function.rename-function.php
bool rename_function ( string $original_name , string $new_name )
Renames a orig_name to new_name in the global function table. Useful
for temporarily overriding built-in functions.
I believe that if you rename the original to original_mysql_query, then add your replacement function which does your logging and then calls original_mysql_query etc, that you will achieve your goal, assuming that you have the way to inject the rename on every page that will call MySQL_query. Most large sites have common code that is included at the top of every page that could do that for you.
There is also a built in php function called override_function (mentioned by ChrisH). It is not fully documented in the php man page but the user comments below the doc give you the information that you need to use it if you prefer it to the rename_function function. There was a discussion about being limited to one override if you needed to call the original function from the replacement. Using the rename_function instead of the override function eliminates that potential restriction.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Override default php function
Is there a way to detect that a function is being called and override with a separate function? I'm not sure function_exists does that.
Override default php function
You can use namespaces to override
existing function names:
namespace blarg;
function basename() {
return 'whatever';
}
$base = basename();
I.e., any call to basename() within
the blarg namespace will use your new
version of the function.
The override_function() function may be what you need, but it seems ugly.
However, using namespaces or inheritance are probably better options.
Why do you want to? There is probably a better solution to the original problem.
Also, do you want to override a built in PHP function, or one that you have written yourself. Is it a method on an object, or a static function?