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
Related
I know you can do something like this in PHP5:
function sayHi() {
echo "Hi!";
}
$func = "sayHi";
$func();
It is called a variable function in the documentation. But the docs don't say anything about what versions of PHP this works on. This could mean it works on ALL versions of PHP, but I doubt it. Specifically, does this work on PHP4?
For php 4.3 they are working. Build-in function test here, your source test here.
Definitely Yes. As you can see in here when there is a dependency in a certain function they set it below the title.
No dependcy in version of php
VARIABLE Functions
With dependency in version of php
INTVAL Function
note: so whenever you have concerns on a certain function that you will use regards on your php version better consult php.net for info.
I simply want to name a method in my class list(). If I try and do so:
class MyClass {
function list () {
// Do some stuff here
}
}
...I get a parse error (Unexpected T_STRING...). The same is true if I use echo or print - so I am guessing that I am not allowed to name a class method the same as a language construct, and while I cannot find any documentation that explicitly states this to be the case, I suppose it does make sense.
My question is, does anyone know of a work around to this, that will work in PHP 4.3.10? I know this can be done in PHP 5.3+ with closures (or I assume it can, I haven't actually tried) No versions of PHP to date support doing this with closures, but can anyone think of a work-around that does not rely on this, baring in mind that it is the method name that is important here?
EDIT N.B.
I am fully aware of how ancient and dead PHP4 is, but I have no option for this particular project. It is to be run on a platform distributed with PHP 4.3.10, which is a very low resource BusyBox platform with a MIPS processor, for which no compilers are provided. I have managed to create a cross-compiler and successfully build PHP 5.2 for it (I haven't tried 5.3 yet, it would probably involve compiling a newer Apache as well) but regardless of this, the manufacturer insist that this invalidates their warranty.
The dilemma you face will stay until you choose A or B.
A: Choose another function name, one that is not a reserved word.
B: Change PHP so that it provides the language features you need.
__call is not available in PHP 4. list is a reserved word since long time.
And you have not outlined what your specific problem with the class interface is, so I don't see much room for more alternatives.
As B does not look like a real option here, you need to take A.
Hope this helps that you can come to a conclusion.
Reserved keywords are reserved:
you cannot use any of the following words as constants, class names, function or method names
So rename your methods.
You've got two options.
1) rename your method. Unless there's a real reason you can justify your method's name then this is the one you should do.
2) namespace your class. If you wrap your class in its own namespace then you can reuse names that are normally reserved or predefined functions, or defined elsewhere. However you should only use this approach if you know what you're doing, otherwise you can end up causing a lot of confusion.
I'd opt for option 1 unless you have a really really compelling reason why your method name must have the same name as a PHP reserved word.
EDIT: You're using PHP 4 so option 2 is off the table. Your only choice is using a different name for your method. That, or upgrade to PHP 5.3. Even if you don't go with namespacing in the end I'd strongly advise upgrading to PHP 5.3 anyway, as PHP 4 is dead and has been for a long time. There will be no security patches released for it ever again so by running it you're basically making your server very insecure.
Kind of a dirty hack, but you could use the magic methods. PHP4 doesn't really support the __call like php5 does, but it could work with the 'overload' construct. I haven't tested this so I can't be sure..
( http://php.net/manual/en/function.overload.php )
class MyClass {
function __call($func, $args){
if ($func == 'list')
return $this->_list($args);
}
function _list () {
// Do some stuff here
}
}
overload('MyClass');
$myclass = new MyClass();
$myclass->list();
I am new to PHP, and working on a class based web site. So my question is simple. Can I compile the site like I can in .NET?
This would be helpful to me because I changed my IsAAction interface to accept an error callback function as a parameter of the Execute function, and I would like all of my implementations to break so I can easily see where to change them.
Thanks in advance.
PHP can be compiled, as in you can compile it to machine code and prevent a parsing everytime you access a file. That the way accelerator like APC work. But you can't compile it like a .NET DLL with every error checked in advance. It would go against its dynamic nature. Late binding mean it will always check for error at runtime
For your particuliar problem, I would suggest adding Unit Tests to your project. They are very good to have anyway, and they will help you catch error in your interface implementation. I personally couldn't live without them. You may want to check PHPUnit or SimpleTests.
EDIT To understand why PHP can't check your error, just check this snippet of code.
if ($_GET['impl'] == 'interface1') {
interface MyInterface {
function foo($var);
}
} else {
interface MyInterface {
function bar($var, $var2);
}
}
class Implementation implements MyInterface { //Will crash or not depending on the URL!
function foo($var) {}
}
Yes and no. See:
Can you "compile" PHP code?
And:
http://www.phpcompiler.org/
And:
http://www.scriptol.com/apollo.php
https://github.com/facebook/hiphop-php/wiki - although I'm sure there are other answers on here that you'd find useful.
There's a opened topic on stackoverflow that is related.
Can you “compile” PHP code?
Some parties such as Facebook rewrote PHP runtime, or part of it so they make it possible to run compiled php code or other source codes, pretty much whatever you like.
HipHop for PHP
Its not an easy task. But you can do it.
Not to my knowledge. PHP is a script language.
I'm thinking about how to find from where any function was called. The problem is that I need to find where the PHP is calling mail() function. One way will be to use register_tick_function(), but I'll need to open each file and check what is on each line. The project is huge, it will take really long to parse each file in PHP. Any other way? Or option how to override the mail() function?
To override the built-in mail function, take a look at override_function which is part of the Advanced PHP Debugger PECL extension - then you can use debug_backtrace to find out the caller details...
//define code to override mail function (note I've used php5.3 nowdoc syntax to avoid
//the need to escape the dollar symbols!!
$code=<<<'CODE'
$trace=debug_backtrace();
$caller=array_shift($trace);
echo 'mail() called by '.$caller['function']
if (isset($caller['class']))
echo 'in '.$caller['class'];
CODE;
//install override
override_function('mail', '$to,$subject,$msg,$hdrs,$params', $code);
You can inspect the stack trace with debug_backtrace(). This will contain information about the calling method/function among others. See the manual for examples.
To add behavior to an existing function, wrap the function into your own function or class and then call this instead of the native function.
To completely redefine a native function, you'd have to install runkit. Then you could do runkit_redefine_function() (or use APD as suggested elsewhere).
If you just want to know where in your project mail() was called, e.g. you do not need to evaluate this at runtime, use your IDE's search function. Eclipse, Zend Studio and Netbeans can do file searches, so it should be very easy to find the calls and also to replace them.
The brute force approach would be to do a global search and replace in your code, replacing "mail\s(" with "my_mail(", then define my_mail and put whatever logging functionality you want there.
Why don't you simply search the source for "mail("?
I take it you have access to the source code?
Why not just use an editor like jEdit, and find all occurences of mail(* in all open buffers?
Or do you really need to know the line numbers at runtime? I can't imagine that you actually do.
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