How can I redeclare, overwrite or rename a function in PHP4? - php

I am looking for a way to redeclare, overwrite or rename a function in PHP4, in order to perform a unittest on a class that makes a call to another function. I want this function to be a test function instead.
I have several constraints:
It has to work for PHP4.
It has to work right out-of-the-box WITHOUT installing something else. (No adp or whatever).

Technically, it is possible using the override_function() or rename_function() functions.
That's not a very clean way to handle it though, and instead I'd recommend that you update your class to allow you to redirect the call somewhere else.
For example, you can change this:
class MyClass {
public function doSomething() {
...
do_complex_calc();
...
}
}
To something like this:
class MyClass {
public $calc_helper = 'do_complex_calc';
public function doSomething() {
...
$helper = $this->calc_helper;
$helper();
...
}
}
$x = new MyClass();
$x->calc_helper = 'another_func_for_testing';
$x->doSomething();
That can be cleaned up even more, but it shows the general idea. For example, I wouldn't recommend leaving the $calc_helper variable as public - I'd implement some sort of a method to let you change it instead.

for overwriting the function you can check if function exits using function_exists but you can redeclare the function
if (!function_exists('function_name')) {
// ... proceed to declare your function
}

Related

PHP: Logging or tracking when an inherited class calls a parent function

I'm in the process of trying to track outdated or unused functions inside an object class. One idea I had was to create a new class that inherits that original class, and then "track" when that parent's functions are called. When detected, I will migrate the parent's function into the child until eventually only the necessary/needed functions exist.
Is there code that does this automatically within PHP? Here is in example.
class OldUser {
function getFullName() {
return "{$this->firstName} {$this->lastName}";
}
}
class User extends OldUser {
}
-----
$user = new User;
echo $user->getFulLName();
Then in a log somewhere I note:
"{timestamp} function getFullName() called"
Obviously I could add these logs manually, but if there is an existing way for PHP to do it I'd love to default to that methodology.
Alternatively, if there is a better way to do this I am open to suggestions.
Thanks!
If your code is too magic for static code analysis tools, you should probably write some integration/functional tests for your app and take a look at code coverage - non-covered methods may be a dead code (or you need more tests). After this you will not only have cleaner code, but also useful test, so two birds with one stone. :)
One possible way to achieve this without having to manually add the calls is to use a class that doesn't inherit the class you want to track/log:
Something around these lines should do it:
class User{
private $old_user;
// use the same signature of your class constuctor here
public function __construct($arg1, $arg2, ...)
{
$this->old_user = new OldUser($arg1, $arg2, ...);
}
public function __call($name, $arguments)
{
log(sprintf("%s: function %S() called", date('Y-m-d H:i:s'), $name));
call_user_func_array([$this->old_user,$name], $arguments);
}
}
All you need to do from there is implement all of the public methods of OldUser and have those calls trigger the logging and then call the parent function. eg:
class User extends OldUser {
protected function log($method, $backtrace) {
// ...
}
public function getFullName() {
$this->log(__METHOD__, debug_backtrace());
return parent::getFullName();
}
}
debug_backtrace() will allow you to track down where in the code that the function was called.

Running code in a PHP once

I'm trying to write a class in PHP that acts as a wrapper for a collection of command line tools to make them easier to use from PHP.
I have a single class (MyClass) in a file myclass.php.
I have code that checks to see if the required tools are installed and then sets a constant (TOOLS_AVAILABLE) to either true or false. Although it's not a lot of code, I only want it to run the first time somebody tries to instantiate my class or use any of its static functions. What's the best practice for handling this?
I only want it to run the first time somebody tries to instantiate my class or use any of its static functions.
Well, the best answer is not to have any static methods. Then you can stick the code in a constructor method as per the answer by #treegarden.
If you must have static methods, then you'll need a static flag within the class to indicate when you've called the 'run once' code, so you can avoid running it again. And then call it explicitly from each of your static methods and the constructor. Something like this:
<?php
class myClass {
private static $hasRunOnce = false;
private static runMeOnce()
{
if (!self::$hasRunOnce) {
self::$hasRunOnce = true;
//put your 'run once' code here...
}
}
public static oneOfYourStaticMethods()
{
self::runMeOnce();
//put your static method code here...
//this would be the same for each of your static methods and your constructor.
}
}
Hope that helps.
You need to create a __construct function in your class and put whatever code you want to execute on instantiation in there:
class MyClass {
function __construct(/* arguments */) {
/* your code here */
}
}
The code will get executed only once when someone instantiates the class.

Call Function From One Function To Another In A Class PHP

I would like to use a function from inside my class in another function. I have tried just calling it but it does not seem to work. Here is what I am doing:
class dog {
public function info($param) {
//Do stuff here
}
public function call($param2) {
//Call the info function here
info($param2);
//That does not seem to work though, it says info is undefined.
}
}
So basically my question is how do I call a function from another in a class. Thank You, I am VERY new to classes! :D
In PHP you always need to use $this-> to call a class method (or any attribute). In your case the code is:
public function call($param2) {
//Call the info function here
$this->info($param2);
//That does not seem to work though, it says info is undefined.
}
Please note that If you declare your method as static, then you will have to use either self:: or static::.
This is a basic PHP OOP syntax, for more information read the doc

PHP non-client coder class execution

Simply question of theory
When building a class that is not going to be used by any other client-coders, what is the best method of execution? Consider the following:
class Test
{
public function __construct()
{
$this->foo();
$this->bar();
}
public function foo(){ //do something }
public function bar(){ //do something }
}
$test = new Test;
As I know exactly what I want this class to do, and the order it should be done in, I simply call the functions during construction. However The same can be done by doing:
class Test
{
public function __construct(){}
public function foo(){ //do something }
public function bar(){ //do something }
}
$test = new Test();
$test->foo();
$test->bar();
What are the advantages to doing it one way or the other? Be it performance, debugging, etc.
Edit
This is a general purpose question. Looking to hear all possibilities and concerns regarding these two ways of executing methods within a class.
In the 1st way you can make those functions private and use them only within the object itself.
class Test
{
public function __construct()
{
$this->foo();
$this->bar();
}
private function foo(){ //do something }
private function bar(){ //do something }
}
$test = new Test;
//so:
$test->foo(); //will throw an error
If you make the functions protected instead of private, any class that inherits from this class would be able to to use the functions (while still not allowing for the functions to be called on the outside)
With your second option, any object can call those functions outside the class definition, and depending on your code, you might not want that.
To elaborate on Neal's answer: If you can, make the functions private. That way, if you want to change them later, you know they are only used within their class.
So, to answer you question: The first answer is preferred because is makes your code easier to maintain. Performance wise, there is no difference.

PHP: run class method when another class method is run?

PHP:
run function when a specific class method is run
what I want is to run some additional functions when a class method is run without altering the already existing class.
how?
With a decorator:
class MyClassDecorator
{
protected $decoratedInstance;
public function __construct($decoratedInstance)
{
$this->decoratedInstance = $decoratedInstance;
}
public function methodNameInOriginalClass()
{
$this->decoratedInstance->methodIWantToRunBefore();
$this->decoratedInstance->methodNameInOriginalClass();
$this->decoratedInstance->methodIWantToRunAfter();
}
public function __call($method, $args)
{
if (method_exists($this->decoratedInstance, $method)) {
return call_user_func_array(
array($this->decoratedInstance, $method),
$args
);
}
}
}
The above assumes that the methods you want to call are public on the $decoratedInstance.
That is not possible, you will have to alter the function to achieve that. But you might be in need of an observer pattern (The zend guys describe the observer pattern on zend.com, too)
Your best bet is to extend the original class and override the method adding your code.
class MyClass extends OriginalClass
{
public function originalMethod()
{
parent::originalMethod();
// My code...
}
}
$myClass = new MyClass();
$myClass->originalMethod();
What you are trying to do is called Aspect Oriented Programming.
Currently PHP has not support for that out of the box, although you can use extensions. Here is post that explains some of the options: http://sebastian-bergmann.de/archives/573-Current-State-of-AOP-for-PHP.html
runkit: Replace, rename, and remove user defined functions and classes.
funcall: Call callbacks before or after specified functions/methods being called.
intercept: Allows the user to have a user-space function called when the specified function or method is called.
not that using these is necessarily a good idea.

Categories