Defining class methods in PHP

2020-03-02 03:20发布

问题:

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

回答1:

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.



回答2:

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);


回答3:

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);
        }


    }

}


回答4:

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.



回答5:

No.

You can extend previously declared classes, though, if that helps.



回答6:

No it is not posible. if you define function/method outside class construct it becomes global function.



回答7:

C++ can't do this either. Did you mix up declaration with definition?



回答8:

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.



标签: php class