it is possible to extend a php function? - php

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.

Related

Overrule a native PHP function only within a framework

Is is possible to overrule PHP's native functions? In my case looking for a way to overrule the empty() function only within my (own) framework. This is because of auto generated datamodels which seem to ignore my __get() method and __isset() will not always result in valid result.
Can this be done like we also can register multiple autoloaders and create structures with inherited methods from the OOP principles? I only need this to work in the framework.
The only way I am aware of to redefine functions in PHP (apart from modifying the source code) is with runkit - although there is pretty much never a time when this is the right answer to a problem. However, even this probably won't work with empty(), because it is a language construct and not a function.
You should rather write a function yourself that either calls empty or does some magic regarding those problematic classes of yours.
Or otherwise fix the classes so they work with empty, but I would choose the first. Many PHP functions dont't do exactly what you want, so if you got a framework anyway, I would wrap most of them so you always have the possibility to add your own functionality.
You can use override_function on the Advanced PHP debugger to do this.
If I'm understanding your problem correctly, empty($foo->bar) is not triggering Foo::__get(), right? This is technically correct behavior, as $foo->bar does not exist, so of course it's empty. You have several options to get the behavior you're looking for, but most of them involve defining your own function or class method which does use Foo::__get(). For example:
public function isEmpty($prop) {
$foo = $this->__get($prop);
return empty($foo);
}
Hope that helps.

Ways to avoid singleton when calling a object inside a global function?

I built some the following i18n function which is called several times when rendering view :
function e_($text)
{
$t = Translate::Instance();
vprintf($t->_($text), array_slice(func_get_args(), 1)); // outputs translated text
}
Currently, I get the instance of the Translate singleton Class inside the function.
I've read that dependency injection should be used instead.
But If I do use dependency injection, I will have to pass the Translate object each time into the function, right ?
This would became :
<?php e_('my text', $this->Translate);
and not simply <?php e_('my text'); ?>
Well I'd like to avoid that.
The way you use the e_ function is actually using an alias. That's fine as long as you can live with it. You don't need to use a singleton to implement an alias:
function e_($text)
{
return $GLOBALS['e_alias']->alias(func_get_args());
}
When setting up the view layer, set the dependency:
$GLOBALS['e_alias'] = $translate;
In application context, set the global variable $translate. This will allow you to move away from the singleton (which are liars), and you actually only need a global variable.
Additionally it allows you to test views with the e_ alias against different translation implementations.
The downside is that you need to manage a list of all these special global variables, like you need to maintain for the global functions like e_.
See as well this answer to the Getting $this inside function question.
True. The reason you would use dependency injection instead is so that you could swap out the translation method for any particular use of e_().
In this particular case, I'm not sure it would be worth it unless you wish to test different translation methods during testing.
One thing you could do to help a little with performance is make $t static so that Translate::Instance() is only ever called once no matter how many calls to e_() are made.

Hooking into function calls in php

A little background: At runtime I would like to be able to inspect the currently called functions javadoc-style documentation, to determine its formal (typed) declaration. This would allow runtime type checking (for simple and complex types) by means of reflection (at a cost) during debugging and testing, something that I would find immensely helpful.
So, in php I would like for a user defined function to get called whenever any other function is about to get called. That is, if a function foo() gets called, I would like to have my callHookHandler() function called immediately before.
One solution would be to implement __call() in all user defined classes, but that is both unwieldy and doesn't include support for functions defined outside classes, so I am looking for a better solution.
This sounds a bit of a fun one so I'm going to give answering it a try.
I hope this helps you. Let me know how it goes.
So, what you are asking can be done, and here's how:
For Functions:
Get all defined functions with $function = get_defined_functions().
Loop through the $functions['user'] key and inspect each one with the ReflectionFunction class. You'll need to get:
The comment using ->getDocComment()
The arguments using ->getParameters()
Do some magic (I'll let you figure out how to parse the comment using some regular extressions and match it up with the parameter list from the reflection. Don't forget optional parameters!)
Rename the function using runkit_function_rename
Generate code in a string that checks the parameters and calls the renamed function
Generate a parameter list as a string
Create a new function with runkit_function_add using the code you generated in step #5 and the parameter list from step #6.
For Classes:
Get a list of classes with $classes = get_declared_classes();
Loop through each one and inspect it with ReflectionObject and ->getMethods() to get the methods. Make sure that the class is not internal with ->isInternal() because we can't do anything about the internal classes.
In an inner loop... go through each method using the ReflectionMethod class. Get the arguments and PHPDoc/JavaDoc comments just like you did with normal functions.
Do the same thing you did with the functions only use runkit_method_add and runkit_method_rename instead.
Downsides:
You won't be able to do the checking on internal class methods and functions (which is fine because they won't have doc comments anyway).
This is a lot of work! I left a lot of parts up to your imagination to avoid this being the length of a short book.
Please send me this or open source it and let me know when you finish, I really want to use this myself. Contact info is on my website which is in my profile ;)
Alternatively:
You can use XDebug's function trace along with reflection then analyze the results after the fact so that you don't have to dynamically edit the code. If you want to write unit-test you could even automate it.
Hope type checking makes it into future versions of PHP and wait: https://wiki.php.net/rfc/typechecking
Notes:
This class reference has a potentially useful example of parsing docComments in the comments section of the page:
http://us.php.net/manual/en/class.reflectionmethod.php
References
get_defined_functions
get_declared_classes
ReflectionFunction
ReflectionObject
ReflectionMethod
runkit
Alternative way to hook into function call is to use a trick with namespaces: Intercepting Execution of System Functions in PHP
You can also use the Go! framework to define an aspect to intercept the execution of system functions automatically.

Get a called functions list in PHP

In PHP, get_included_files() returns an array with the names of included files.
In a similar fashion, is there any way to get an array with the names of called functions with parameters?
In this way, Is any way to get an array with the names of called functions with parameters?
No.
What you can do is a debug_backtrace() which will show all the function calls (with parameters) that lead to the execution of the line you are doing the backtrace from (the "call stack"), but that's different from all functions that were ever called in the script.
What do you want to do? Maybe there's a different approach.
I was searching for something similar and found xdebug's tracing very useful.
Here's an example of how it could look like:
http://devzone.zend.com/1135/tracing-php-applications-with-xdebug/
I was trying to achieve what you want and finally came up with an reasonable solution.
Make a class named Debug and include that above every file you want to debug in. Build yourself a function that prints nicely the information stored in $calls.
class Debug {
private static $calls;
public static function log($message = null)
{
if(!is_array(self::$calls))
self::$calls = array();
$call = debug_backtrace(false);
$call = (isset($call[1]))?$call[1]:$call[0];
$call['message'] = $message;
array_push(self::$calls, $call);
}
}
Call this function everytime you declare a function first line in the functionbody: Debug::log($message(optional) )
Not that I'm aware.
You can however use debug_backtrace to get the currently active function/method hierarchy.
I don't think there's a way to do what you want. Sorry.
The closest I can get is the function_exists() function, which will tell you whether a specific function has been loaded.
What exactly do you want to achieve here? I can't see a use case (outside of a php_info() type screen) that would require a list of available functions.
You will have to install it as an extension, but a profiler like XHProf will give you a breakdown of which functions are called and how long they take, as well as a callgraph.
XHProf or Webgrind/KCachegrind will show you the functions called, but not their parameters.
You could also use get_defined_functions, which gives you a list of all functions defined. But it won't show you which functions have actually been called, and with what parameters.
If you really need to know the parameters, I don't know of any tools other than a custom logger like the one Henze provided in his answer.

Can I include code into a PHP function or method?

I want to make a kind of "generic" function which gets executed and - depending on what to do - includes it's implementation file via include(). So for example, I might have exactly one function and exactly 20 procedure files for that function. The procedure files may look like do_this_procedure.php, do_that_procedure.php, etc.
As I'm new to PHP I'd like to know from PHP expertes wether this is fine with PHP or not, before I try it and only "believe" it works, and in reality a lot of things go wrong. So what do you think? Currently I think of an include just as an insertion of code right into that place before it gets compiled for execution.
From the include statement documentation:
If the include occurs inside a function within the calling file, then all of the code contained in the called file will behave as though it had been defined inside that function. So, it will follow the variable scope of that function. An exception to this rule are magic constants which are evaluated by the parser before the include occurs.
So yes, you can call include from within a function and use that to define the body of the function. You can even have the file that you include vary with each call to the function. The downside is the include will be evaluated with each call to the function; if the function is called many times, it could seriously impact performance.
Depending on exactly what you're trying to accomplish, an alternative is to follow a functional programming paradigm, which lets you construct functions at runtime. Before PHP 5.3, it's ugly, so I wouldn't recommend it unless you can require at least PHP 5.3.
You may try this too:
PHP Tokenizer.
//from external script:
<?php
var_dump(token_get_all(file_get_contents('myscript.php')));
?>
Including such file will be done on runtime, I believe. Basically, when PHP hits the include/require function, it will eval that file as an independent one.
I'm not sure whether variables passed to the function will be usable in the included file, but global-ing them should work fine.
#outis hit the nail on the head, but an alternative approach would be to create the function as a static method in a class and create an autoloader (via spl_autoload_register, etc.) to include and call the class method at runtime.
Then again, this really wouldn't really buy you anything unless you're already using an OO approach.
outis is correct, however this strikes me as a very ugly and messy way to implement the code. Why not just have different files with different declarations of a function including the function declaration.
Functions should be as short as possible - as a general rule of thumb I will go back and see if it is practical to refactor any function longer than 20 lines. Bearing this in mind, where's the benefit in including the body of a function from a seperate file?
C.

Categories