简体   繁体   English

不使用$ this-> function_name()调用类函数 - PHP -

[英]Calling a Class function without using $this->function_name() — PHP --

So I have this class: 所以我有这门课:

class A{
      public function do_a(){ return 'a_done';};

      public function do_b(){ return 'b_done';};
}

So I require the php file and create an instance of the class: 所以我需要php文件并创建该类的实例:

require_once("A_class.php");
$System = new A();
require_once("user_calls.php"); //here I import the user file with the function calls.

user_calls.php contents: user_calls.php内容:

echo 'this was the result of '.$System->do_a();
echo 'this was the result of '.$System->do_b();

So, that does work, but I don't want the user to have to use $System->do_a(); 所以,这确实有效,但我不希望用户必须使用$System->do_a(); , but only do_a(); ,但只有do_a(); .

Any solutions? 有解决方案吗

EDIT: I also want to limit the functions the user could call in the user_calls.php file, to basic native php functions and those in class A. 编辑:我还想限制用户可以在user_calls.php文件中调用的函数,基本的本机php函数和A类中的函数。

DISCLAIMER: While this code works, and does what you requested, that doesn't mean that I advocate coding like this. 免责声明:虽然此代码有效,并且按照您的要求执行,但这并不意味着我提倡像这样编码。 It's very hard to follow for other developers (and maybe even you in the future...), and it also makes use of eval() , which is almost always A Bad Thing(tm). 对于其他开发人员来说很难跟上(甚至可能在将来也是如此......),它也会使用eval() ,这几乎总是一件坏事(tm)。 That said, here you go: 那就是说,你走了:

<?php
class A {
    public function do_a() {
        return __METHOD__;
    }

    public function do_b() {
        return __METHOD__;
    }
}

$aRef = new ReflectionClass('A');
$aPublicMethods = $aRef->getMethods(ReflectionMethod::IS_PUBLIC);

foreach ($aPublicMethods as $method) {
    $php = <<<PHP
function {$method->name}() {
    global \$System;
    return \$System->{$method->name}();
}
PHP;

    eval($php);
}

$System = new A();

echo 'this was the result of ' . do_a();
echo 'this was the result of ' . do_b();

Please also note that if your methods use arguments, things get even more hairy. 还请注意,如果您的方法使用参数,事情会变得更加毛茸茸。 Also, if you name any of your methods the same as a function in the global namespace (ex. substr() ), this will attempt to redefine them, and you'll probably get a Fatal Error. 此外,如果您将任何方法命名为全局命名空间中的函数(例如substr() ),则会尝试重新定义它们,并且您可能会收到致命错误。

Methods of a class are either instance methods (they act on a particular instance of a class defined by $this) or they are class methods (They aren't tied to any one particular instance of a class, but provide services that fall within the remit of the class. 类的方法是实例方法(它们作用于由$ this定义的类的特定实例)或者它们是类方法(它们不依赖于类的任何一个特定实例,而是提供属于该类的服务。课程的职权范围。

An instance method is defined as follows: 实例方法定义如下:

public function foo()
{
}

whereas a class method is defined with the STATIC keyword. 而使用STATIC关键字定义类方法。

static public function bar()
{
}

In the instance method you can use $this to get access to the state of the instance on which the method was called. 在实例方法中,您可以使用$ this来访问调用该方法的实例的状态。 This is not available in the class method because it's not tied to any one instance. 这在类方法中不可用,因为它不依赖于任何一个实例。 It can access other members of the class (provided they're not tied to an instance) with the self keyword though. 它可以使用self关键字访问类的其他成员(假设它们不与实例绑定)。

Instance methods are called as follows: 实例方法调用如下:

$a = new ObjType ()
$output = $a -> foo ();

Class methods are called as follows: 类方法调用如下:

$output = ObjType::bar ();

No matter which approach you use you either have to provide an instance (for instance methods) or a class (for class methods) to call the method. 无论您使用哪种方法,您都必须提供实例(例如方法)或类(用于类方法)来调用方法。 Calling just foo() or bar() will not work. 只调用foo()bar()将不起作用。

You'll have to use a closure. 你必须使用一个闭包。 Note that it's calling directly from the class definition, not the object: 请注意,它直接从类定义调用,而不是对象:

class test {
    function method() {
        echo 'method was called';
    }
}

$method = function(){call_user_func('test::method');};
$method();
$method();
$method();

//output:
//method was calledmethod was calledmethod was called

To call the method from the object, rather than the class, you'll have to pass the object into the closure: 要从对象而不是类中调用方法,您必须将对象传递给闭包:

class test {
    var $count = 0;
    function method() {
        $this->count++;
        echo $this->count . "|<br />";
    }
}

$obj = new test;
$obj2 = new test;
$method = function($object){call_user_func(array($object, 'method'));};
$method($obj);
$method($obj);
$method($obj);
$method($obj2);
//output:
//1|
//2|
//3|
//1|

But that's not any prettier or simpler, is it? 但这不是更漂亮或更简单,是吗?

If you don't want to clutter up your page, just name the object something short: 如果您不想弄乱页面,只需将对象命名为简短:

$pco = new page_controller_object_with_a_long_name_that_is_annoying;
$pco->do_a();
$pco->do_b();
//etc.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM