PHP on method/function call event - php

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.

Related

Zend 2 Imports and Global Namespace

I'm trying to wrap a legacy application in the Zend2 MVC framework. Thanks to the Zend Skeleton Application and code samples (especially https://github.com/maglnet/MaglLegacyApplication), I've solved most of my issues.
The one big issue I haven't been able to solve is illustrated by the following "legacy" file:
<?php
$test = "test";
function echo_test(){
global $test;
echo "test = ";
var_dump($test); # Makes NULL explicit
}
echo_test();
In the Controller for a ZF2 module, I capture the output of the include using an output buffer and stick that into the response object:
...
chdir($filePath) # Fixes relative includes
ob_start();
include $filePathAndName;
$output = ob_get_clean();
$response->setContent($output);
return $response;
... and I get back test = NULL.
I've seen warnings that ZF2 namespaces can create issues for legacy files and done my legwork to try and clarify why. According to the PHP guide, "Without any namespace definition, all class and function definitions are placed into the global space". Indeed, my sample is only slightly more complicated than the one listed below this statement... but it doesn't seem to work.
I also see that "You can set a variable after declaring a namespace, but variables will always exist in the global scope. They are never bound to namespaces.".
I continued to research and have finally discovered that this approach "will import the contents of the include file into the method scope, not the class scope".
Is there any way to process the file outside the method scope?
This is nothing to do with PHP namespaces. If you're including a file from within a ZF controller action, it will execute within that function's variable scope. For your example to work you'd need to declare global $test; in the ZF action as well before including the file (which would be horrible).
Without knowing exactly what your legacy code looks like it's hard to suggest a good solution. If there are a set number of globals you need to work, you can global them at some point earlier in the ZF application (with the goal of removing that hack at a later date). If you don't know in advance what the globals are, or if there are a large number of them, you may need to edit the legacy code to try and refactor out the reliance on globals.
Another option (at least theoretically) is to use exec(), shell_exec(), passthru() (automatically prints output), or curl (see shell_exec link, but only if you're hosting it outside ZF2 to avoid an infinite loop). This approach has its own list of drawbacks including:
Security (but see escapeshellarg)
Access to $_SERVER (the first comment on the question here may help), $_GET (but see this technique), $_POST, and especially $_COOKIES
A bug (may be resolved) in the php command line

Load Javascript like PHP's include

Today im asking for something, that i cant believe to find on the web.
Im trying to make a javascript function, which allows me to give a filename/pathname as a parameter and the function returns javascript code which will be executed/initialized immediatly - just like PHP's include or require.
Now i tried several technics to realize my approach but i just dont hit the right spot so i might be asking: is it even possible to do that in JS?
Thanks in advance
There are many libraries and standards that exist merely for this purpose. In Node.js, there is a CommonJS implementation built-in. If you want to export a piece of code from a file, or the entire contents of a file, you can attach it to the module.exports or simply exports object. You may then use require('./path/to/file'); to require it in a separate piece of code.
Some libraries try to borrow this approach and implement it on the client side, browserify being one of them.
However, it would do you better to have a look at the best client-side library of them all: RequireJS
RequireJS implements what is called the Asynchronous Module Definition pattern, which loads in all the project dependencies in a top-level file. It gives you access to two functions, require() and define() that take a number of paramaters. The first function simply requires dependencies, while the second one defines a module and name's that modules dependencies, like so:
A top-level file that defines no modules, only uses them:
require(['jquery', 'underscore', 'backbone'], // dependencies
function($, _, Backbone) { // dependencies are passed into callback
$('div').append('Test'); // dependencies are available to this file
}
);
A module:
define(['jquery', 'underscore', 'backbone'], // this module's dependencies
function($, _, Backbone) { // dependencies are made available
var MyModule = {};
return MyModule; // this return statement essentially defines the module
}
);
The great thing about this approach is that by having a top level file and several modules that all define their own dependencies, you only ever need to reference a module if it actually is a dependency of that file, so your top-level stuff is always neat and uncluttered and usually consists of no more than an initialize function.
RequireJS also comes with an optimizer called R.js that can minify and concatenate your scripts in the right order using UglifyJS or Google's Closure Compiler. It's worth checking out.

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.

PHP - override existing function [duplicate]

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

PHP - recognize when the function was called

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.

Categories