This is a bit of a crazy idea, but would there be a way to bootstrap all the functions that php have without using a helper function to call the functions.
What I mean is actually calling some code or function before and after every basic function call.
Example:
<?php
echo "Hello";
?>
But these functions would be called before echo and after echo:
<?php
function pre_echo()
{
do_something();
}
function post_echo()
{
do_something_else();
}
?>
"Bootstrapping" is not the correct term here - what you want to do is called Aspect-oriented Programming, and yes, it can be done in PHP. However, it seems to require substantial changes to the way you normally use PHP.
Just as an FYI, your example picked something which isn't actually a function in the strictest sense, echo is a language construct and handled differently by the PHP internals.
I think there's only two ways to achieve what you are after though:
Preprocess your PHP code to augment
it with overridden function calls
or, modify the PHP internals to
support hooking all function calls
Why do you want to do this? If you want to profile your code then use a profiler like Xdebug
This is why you write your own classes and encapsulate the functionality you want to have for that specific case there. Why make your stuff harder to understand for another programmer?
you can do this.
you need change the php.ini file
at the directives
auto_prepend_file
auto_append_file
for example
auto_prepend_file=/home/php/run_before.php
auto_prepend_file=/home/php/run_after.php
then
<?php echo('hi'); ?>
the output will be:
# something before
hi
# something after
Related
Having functions that are quite big and they are loading every time the page is loaded, would be better to write function foo(){ include(.../file_with_function's_code); return; } to minimize the size of the functions script? Or it doesn't matter because when a function is loaded (but not executed) also is loaded the content even if it is into an include? Thank you.
(Edit: my question is not about if it's possible or not)
While #Luceos answer is technically correct (the best kind of correct), it does not answer the question you asked, namely is doing this better, or do includes happen regardless of function calls?
I tested this in the most basic way (OP, why didn't you?):
<?php
echo "Testing...";
function doThing() {
include nonExistantFile.php;
}
//doThing();
echo "Done testing.";
Results:
if I call doThing(); I get a file not found warning.
If I comment out doThing();... there is no error! So you can save file load time by doing this.
Or, as a good alternative, encapsulate your functions in classes, and take the benefit of __autoload :
function __autoload($class_name) {
include $class_name . '.php';
}
Encapsulate myBigFunction() in a class
class myBigFunction {
public static function run() {
//the old code goes here
}
}
save it as myBigFunction.php
When you call the function as static method on the class :
myBigFunction::run()
__autoload will load the file, but not before that.
Yes that's possible; see http://www.php.net/manual/en/function.include.php
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.
Question is, why not add the surrounding function definition to that included file. I think the only viable reason to include within a function is to split code within that function into bits.
Both Luceos' and Albatrosz could be misread, so I felt that I should clarify these.
The include set of directives generate a runtime ZEND_INCLUDE_OR_EVAL operation which calls the Zend compiler to compile the referenced file. So in general you should not embed include statements in a function, as:
The include will be executed every time that code path is taken when the function is called. Compiling the same bit of code 100s of times is a bad idea.
If the code contains elements of global scope (e.g. function or class declarations) then executing that declaration even twice will cause compiler errors.
So don't unless you know what you are doing. Use techniques such are those described by Albatrosz. Incidentally his __autoload() function is just the sort of example of an exception where this is valid to do.
I'm always using a function to write to a log file, but this function is defined in a file among many other things that I don't need to include.
I was wondering, is it possible to define a function somewhere inside php to make it available without the need to include the source file? Sort of like how I can just use echo or die, or isset. Could I create my own function to use it this way?
Thank you.
No. To do that, you'll have to write a PHP extension in C. Any PHP code will always need to be included explicitly one way or another.
PHP has the option to always automatically include a file at the beginning though: http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
Actually, you need to make a module with your function.
Other ways:
make autoload. http://www.php.net/manual/en/language.oop5.autoload.php
put only this function to other file and include it everytime you need.
you can add you log class in set_include_path path or add this function to pear library class
This code don't work. Why not?
<?php
function test()
{
echo 'test';
}
runkit_function_rename('test', 'test2');
test2();
?>
What I really want is this. I'm using a system that have a function. When I'm on localhost I want that function to do something different. I want to override the function with own stuff.
All alternatives are welcome as well.
Do you have the PECL extension installed?
http://www.php.net/manual/en/runkit.installation.php
This ยป PECL extension is not bundled with PHP.
I never had any luck with Runkit either.
You asked for alternatives, and I can definitely recommend this one:
Patchwork
Patchwork is a PHP function-override library. In other words, it does much the same job as Runkit.
The main difference is that it is written in pure PHP - no extensions to install; just a require_once() at the top of your code.
The flip side of this is that because it's pure PHP, it can only replace functions defined within your program; ie it can't override a PHP built-in function like Runkit can. The example in your question will work fine with Patchwork, but trying to override a PHP function like mysql_query() is not possible.
However, unlike Runkit, it works perfectly, so if you can live with that limitation, I'd strongly recommend it.
Another alternative to Runkit that you might want to try is PHP Test Helpers. This is a PHP extension, and covers pretty much the same ground as Runkit. It's written by the same author as PHPUnit, so it should be pretty good. However I didn't have much joy when I tried to install this either, so I can't really comment on it much.
I note from your comments elsewhere on this question that you're running Windows (ie WAMP). Neither Runkit nor PHP Test Helpers are provided with Windows executables; in order to use either of them in Windows you need to compile the extension yourself from the C source code. For this reason, if you're on Windows, then Patchwork is your only sensible choice.
What I really want is this. I'm using a system that have a function. When I'm on localhost I want that function to do something different. I want to override the function with own stuff.
All alternatives are welcome as well.
function test() {
if($_SERVER['HTTP_HOST'] == 'localhost' {
// do one thing
} else {
// do other thing
}
}
If you're set on using runkit, you'd need to use runkit_function_redefine, not runkit_function_rename to make the same function do different things.
As explained earlier, it's probably best to differentiate inside of a function body regarding the value of $_SERVER['HTTP_HOST'].
Although I'd personally see this as bad style, you can even define function inside of other functions or blocks.
This snippet defines one function get_template_part():
if($_SERVER['HTTP_HOST'] == 'localhost' {
function get_template_part() {
}
} else {
function get_template_part() {
}
}
Unfortunately, this wouldn't help in your case, since get_template_part() is already defined outside your reach.
Someone might also experience that runkit_function_* functions are not working although the runkit library is installed correctly. This is because these functions are broken for some PHP versions (probably at least all 5.2.*) as can be seen here: https://bugs.php.net/bug.php?id=58205
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.
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.