OK so is there a way in php do track function calls such as
function Tracker($name,$returnedValue,$file,$line)
{
echo $name . '() was called and returned a ' . typeof(returnedValue);
}
function test(){}
test();
The reason for this is to send a custom framework data type back so another example would be
$resource = fopen('php://stdin'); //This would return an instance of (Object)Resource.
if($resource->type == 'fopen')
{
//Code
}
I have never seen anyway to do this but does anyone know if it is possible ?
It's not possible to do this using just PHP, a debugger might help, however you could wrap the function:
function wrapper()
{
$args=func_get_args();
$function=array_shift($args);
$returned=call_user_func_array($function, $args);
print "$function (" . var_export($args, true) . ") = "
. var_export($returned, true) . "\n";
return $returned;
}
$value=wrapper('test_fn', 1 ,2 ,3, 'something');
$value=wrapper('mysql_connect');
I don't understand your explanation of what you are trying to achieve here.
C.
Not really. Xdebug is able to log function calls though: http://xdebug.org/docs/execution_trace
Maybe you want something like Observer pattern?
http://en.wikipedia.org/wiki/Observer_pattern
Related
I use internal function function_exists, that can return true but I can't find the custom function in my project. I also debugged my code to trace the function, but the debugger does not step into my custom function. I very look forward to know why. Please help me, thank you.
To find out where is the function defined, use following code:
<?php
$rf = new ReflectionFunction('my_fuction_name');
echo 'file:' . $rf->getFileName() . ', line:' . $rf->getStartLine();
?>
Please note that if the function is not defined in source code, but it's internal PHP function, both getFileName() and getStartLine() will return false.
You can check if the function is internal that way:
<?php
$rf = new ReflectionFunction('my_fuction_name');
if($rf->isInternal() === TRUE){
echo "Function is internal!";
}else{
echo "Function is not internal.";
}
?>
Suppose I have the following PHP code:
class Foo {
function getBar() {
return 1;
}
}
function check( Foo $foo ) {
if ( $foo->getBar() == 1 ) {
// here could be more code ...
return 'Oh no, there was an error in class' .
get_class( $foo ) . ', method ' .
'getBar';
}
}
The last string in check bothers me because if Foo::bar gets renamed by a refactoring tool, the error message will be wrong. Is there any way to get around this without using a string somewhere?
You can use __METHOD__ to get the name of the current method.
But to get reference to other method that would allow you some kind of automatic refactoring - no, it's not possible in php.
Can be done by using method_exists()
class Foo {
function getBar() {
return 1;
}
}
function check( Foo $foo , $method = 'getBar') {
if (!method_exists($foo, $method) ) {
// here could be more code ...
return 'Oh no, there was an error in class' .
get_class( $foo ) . ', method ' .
$method;
}
}
It is not possible in PHP per se, but you can implement such a feature. One possible implementation would work as follows: somewhere the file path, class name, method name and some kind of a description of where and what should match what. Your new feature whenever triggered would check the given files, check whether some values changed, fix whatever needs to be fixed and log a report about the task. It would not be simple to implement something like this, but, important to note is that there is a solution.
Anyone have any ideas... there's like 15 places this function is getting called, every time it hits it seems to be the problem, it gets through the function but the serialized length of :
echo "Length serialized: " . strlen(serialize($this->_items));
comes out to be about 8000 long.
public function getItemsCollection($useCache = true)
{
if (is_null($this->_items)) {
$this->_items = Mage::getModel('sales/quote_item')->getCollection()
->addFieldToFilter("quote_id", $this->getId())
;
#$this->_items->setQuote($this);
}
echo "Length serialized: " . strlen(serialize($this->_items));
exit;
return $this->_items;
}
Seems to me like there is something weird in the item object. Like one of its members has a large object tied to it. I know that I had issues saving addresses to a session object. Maybe there is something you are doing outside of this that is attaching a large object that errors out. You could do the following to get the raw sql and run it on your database to see what comes back
public function getItemsCollection($useCache = true)
{
if (is_null($this->_items)) {
$this->_items = Mage::getModel('sales/quote_item')->getCollection()
->addFieldToFilter("quote_id", $this->getId())
;
#$this->_items->setQuote($this);
}
echo (String)Mage::getModel('sales/quote_item')->getCollection()->getSelect();
exit;
return $this->_items;
}
i had same issues when i coded with Magento, it's linked to recursion, try var_dump() instead of echo()
if someone could help me to improve this function to use it with this format (from scratch, not tested):
<?php
define("LINEA", __LINE__, true);
function line($string)
{
return $string . LINEA;
}
echo line('Error: ');
?>
Example of current use:
<?php
function line($startText, $line, $endText = NULL)
{
$endText = !empty($endText) ? $endText : '';
return $startText . $line . $endText;
}
/*
...
lot of code
...
*/
echo line('Error on line: ', __LINE__) . '<br />';
/*
...
lot of code
...
*/
echo line('Alert - ', __LINE__, '!');
?>
Outputs:
Error on line: 12
Alert - 18!
You might consider using debug_backtrace to obtain information about the function caller, including line, file, class, the current scope, and much much more. This way you don't need to pass any of the line number information into your error logging function.
Be aware that generating this information can be somewhat of a drag on performance.
You should also consider using an existing logging package, like PEAR's Log, Zend_Log, or Apache log4php.
It doesn't look like your line() function is doing you any good any more. Why don't you just call:
echo 'Error on line: ' . __LINE__;
Given this class:
class Tacobell{
public function order_taco(){
echo "3 Tacos, thank you.";
}
public function order_burrito(){
echo "Cheesy bean and rice, please";
}
}
$lunch = new Tacobell;
$lunch->order_burrito();
$lunch->order_taco();
How would I do something like this?
$myOrder = 'burrito';
$lunch->order_.$myOrder;
Obviously that code is bunk--but shows what I'm attempting to do better than trying to explain it away.
And maybe I'm going about this all wrong. I thought about a method with a switch statement, pass in burrito or taco, then call the right method from there. But then I have to know the end from the beginning, and I may potentially have lots of methods and I'd rather not have to update the switch statement everytime.
Thanks!
How about something like this?
class Tacobell {
public function order_burrito() {
echo "Bladibla.\n";
}
public function order($item) {
if (method_exists($this, "order_$item")) {
$this->{'order_' . $item}();
} else {
echo "Go away, we don't serve $item here.\n";
}
}
}
You would call it using $lunch->order('burrito');, which looks much cleaner to me. It puts all the uglyness in the method Tacobell::order.
$lunch->{'order_' . $myOrder}();
I do agree the design is a little iffy, but that's how to do it at least.
I think call_user_func is what you're looking for:
http://us3.php.net/call_user_func
You can pass it the string you suggested. See example #3 for calling a method of a class.
simple enough
$order = 'order_burrito';
$lunch->$order();