Is it possible in PHP (as it is in C++)
to declare a class method
OUTSIDE the class definition?

- 70,531
- 10
- 51
- 98
-
1As far as I know what you are asking is not possible in C++. You might want to clarify. – erlando Sep 16 '08 at 12:52
-
In C++ you can define functions outside of the class and if the first parameter is of that class type, then you get what looks like an overload (i.e. an explicit "this"). The method is used for things such as the << operator of std::cout, for example. Unfortunately, PHP does not recognize a type when calling a function. The number of parameters is the only thing one can use to distinguish between PHP functions. The function itself can test for a parameter type and act differently upon it, but two functions with the same name and same number of parameters is something illegal in PHP. – Alexis Wilke Oct 13 '13 at 23:03
8 Answers
No, as of PHP 5.2. However, you may use __call
magic method to forward call to arbitrary function or method.
class A {
public function __call($method, $args) {
if ($method == 'foo') {
return call_user_func_array('bar', $args);
}
}
}
function bar($x) {
echo $x;
}
$a = new A();
$a->foo('12345'); // will result in calling bar('12345')
In PHP 5.4 there is support for traits. Trait is an implementation of method(s) that cannot be instantiated as standalone object. Instead, trait can be used to extend class with contained implementation. Learn more on Traits here.

- 37,241
- 25
- 195
- 267

- 12,859
- 7
- 45
- 47
Yes it is possible to add a method to a PHP class after it is defined. You want to use classkit, which is an "experimental" extension. It appears that this extension isn't enabled by default however, so it depends on if you can compile a custom PHP binary or load PHP DLLs if on windows (for instance Dreamhost does allow custom PHP binaries, and they're pretty easy to setup).
<?php
class A { }
classkit_method_add('A', 'bar', '$message', 'echo $message;',
CLASSKIT_ACC_PUBLIC);
$a = new A();
$a->bar('Hello world!');
Example from the PHP manual:
<?php
class Example {
function foo() {
echo "foo!\n";
}
}
// create an Example object
$e = new Example();
// Add a new public method
classkit_method_add(
'Example',
'add',
'$num1, $num2',
'return $num1 + $num2;',
CLASSKIT_ACC_PUBLIC
);
// add 12 + 4
echo $e->add(12, 4);
-
Note that this requires a PECL extension that everyone does not automatically have on their server. Also, it is now called runkit instead. http://www.php.net/manual/en/function.runkit-method-add.php – Alexis Wilke Oct 13 '13 at 23:10
You could perhaps override __call or __callStatic to locate a missing method at runtime, but you'd have to make up your own system for locating and calling the code. For example, you could load a "Delegate" class to handle the method call.
Here's an example - if you tried to call $foo->bar(), the class would attempt to create a FooDelegate_bar class, and call bar() on it with the same arguments. If you've got class auto-loading set up, the delegate can live in a separate file until required...
class Foo {
public function __call($method, $args) {
$delegate="FooDelegate_".$method;
if (class_exists($delegate))
{
$handler=new $delegate($this);
return call_user_func_array(array(&$handler, $method), $args);
}
}
}

- 66,030
- 26
- 140
- 208

- 295,876
- 54
- 310
- 348
As PHP 5.3 supports closures, you can dynamically define instance methods as variables holding closures:
$class->foo = function (&$self, $n) {
print "Current \$var: " . $self->var . "\n";
$self->var += $n;
print "New \$var: " .$self->var . "\n";
};
Taking $self
(you can't use $this
outside object context) as a reference (&
), you can modify the instance.
However, problems occur when you try to call the function normally:
$class->foo(2);
You get a fatal error. PHP thinks foo
is a method of $class
, because of the syntax. Also, you must pass the instance as the first argument.
There is luckily a special function for calling functions by name called call_user_func
:
call_user_func($class->foo, &$class, 2);
# => Current $var: 0
# => New $var: 2
Just remember to put &
before the instance variable.
What's even easier is if you use the __call
magic method:
class MyClass {
public function __call ($method, $arguments) {
if (isset($this->$method)) {
call_user_func_array($this->$method, array_merge(array(&$this), $arguments));
}
}
}
Now you can call $class->foo(2)
instead. The magic __call
method catches the call to an unknown method, and calls the closure in the $class->foo
variable with the same name as the called method.
Of course, if $class->var
was private, the closure in stored in the $class->foo
variable wouldn't be able to access it.

- 477
- 4
- 9
-
Note that the use of & when calling a function is not legal in PHP. It was accepted a while back (probably necessary in PHP 4) but today you get warnings or errors when you run that code `call_user_func($class->foo, &$class, 2);`. – Alexis Wilke Oct 13 '13 at 23:04
-
-
And furthermore, in the latest PHP versions, you can use $this in closures. – jocap Oct 15 '13 at 00:35
No.
You can extend previously declared classes, though, if that helps.

- 5,480
- 6
- 41
- 73
No it is not posible. if you define function/method outside class construct it becomes global function.

- 510
- 2
- 10
-
All functions defined outside of a class are not global. If you save the function in a variable, then it is not global. (`$func = function() {...};`) – Alexis Wilke Oct 13 '13 at 23:17
C++ can't do this either. Did you mix up declaration with definition?

- 530,221
- 131
- 937
- 1,214
No, as everyone has said, it is not strictly possible.
However, you can do something like this to emulate a mixin in PHP or add methods to a class at runtime, which is about as close as you're going to get. Basically, it's just using design patterns to achieve the same functionality. Zope 3 does something similar to emulate mixins in Python, another language that doesn't support them directly.

- 11,039
- 3
- 32
- 38
-
Your statement about Python is incorrect, since Python does support multiple inheritance, and indeed does support defining methods on runtime. – lkraider Mar 17 '12 at 18:24