将其他文件中的函数分配给类

时间:2014-09-30 19:39:43

标签: php

我正在尝试从单独的文件向类添加函数,我想知道这是否可能!

$mClass = new MyClass();
$mClass->new_Functions[0](10);  // Is there a way to have it in this form?

class myClass
{
    private $Pvar = 5;
    $new_Fcuntions;
    function __construct()
    {
        include('additional.functions.php');
        $arr = get_defined_functions();
        $this->new_Functions = $arr['user'];
        // trying to call the function with parameter 10
        call_user_func(array($this, $this->new_Functions[0]), 10);
    }

}

[additional.functions.php]文件

function operate($y)
{
    return $this->Pvar * $y;
}

-----编辑-------因为不清楚! “additional.functions.php”是一个模块,将有多个模块添加到应用程序中,每个模块可以有多个单独的功能,模块可以相互调用!

additional.functions.php [模块文件]

function operate($y)
{
    return $this->Pvar * $y;
}

function do-more($foo)
{
    return $this->operate(20) + $foo;
}

another.functions.php [另一个模块]

function do-another($foo)
{
    return $this->do-more(30) - $foo;
}

function add($foo, $bar)
{
    return $foo + $bar;
}
感谢每一次参与,自从我试图用它来操纵它已经有一段时间了! 这可能还是我应该放弃!

6 个答案:

答案 0 :(得分:1)

在我看来,您正在寻找Traits,这是PHP 5.4.0中的一项新功能。使用traits,你可以将代码片段“混入”到其他类中,这个概念称为“水平重用”。

如果你不是在寻找特质,你有可能用Runkit做你想做的事情,但如果你对PHP内部并不感兴趣,我会建议尽可能远离它。好。

无论如何,无论你想做什么都非常有趣

答案 1 :(得分:1)

我让它与依赖注入一起工作。 pvar必须是公共的或创建一个__get方法来返回私有变量。我还使用了函数名称,因为通过名称而不是它在列表中的位置对我来说似乎更干净但是如果你想保留它,那么只需将$key放在你看到$value的位置}行:$this->function_list[$value] = ...

function operate($y, $that)
{
    return $that->Pvar * $y;
}

class Example {

    public $function_list = array();
    private $Pvar = 5;
    public function __construct()
    {
        $list = get_defined_functions();
        $that = $this;
        foreach ($list['user'] as $key => $value) {
            $this->function_list[$value] = function() use ($value, $that) {
                print call_user_func_array($value, array_merge(func_get_args(), array($that )));
            };
        }
    }
    public function __get($key)
    {
        if (isSet($this->$key)) {
            return $this->$key;
        } else {
            throw new \Exception('Key "'.$key.'" does not exist');
        }
    }
}

$Ex = new Example();

$Ex->function_list['operate'](10);

答案 2 :(得分:1)

如果你想从模块中扩展MyClass(而不是像在你的示例代码中那样初始化它),那么你可以用这样的方式来实现它:

<?php

namespace modules\MyModuleA;

class MyClassExtension
{
    private $MyObject;

    public function __construct(\MyClass $MyObject)
    {
        $this->MyObject = $MyObject;
    }

    public function doSomething($anyParameter)
    {
        return $this->MyObject->doSomethingElse($anyParameter * 5, 42, 'foo');
    }
}

MyClass

<?php

class MyClass extends \Extensible
{
    // some code
}

abstract class Extensible
{
    private $extensions = [];

    public function extend($extension)
    {
        $this->extensions[] = $extension;
    }

    public function __call($methodName, $parameters)
    {
        foreach ($this->extensions as $Extension) {
            if (in_array($methodName, get_class_methods($Extension))
                return call_user_func_array([$Extension, $methodName], $parameters);
        }
        throw new \Exception('Call to undefined method ' . $methodName . '...');
    }

    public function hasExtension($extensionName)
    {
        return in_array($this->extensions, $extensionName);
    }
}

并将它们放在一起:

<?php

$moduleNames = ['MyModuleA', 'MyModuleB'];

$MyObject = new \MyClass;

foreach ($moduleNames as $moduleName) {
    $className = '\\modules\\' . $moduleName . '\\MyClassExtension';
    $module = new $className($MyObject);
    $MyObject->extend($module);
}

// Now you can call a method, that has been added by MyModuleA:

$MyObject->doSomething(10);

您应该为扩展类添加一个接口...

问题是:如果应用程序中的任何代码调用$MyObject的方法,而不存在,则会发生什么,因为模块尚未加载。您总是必须检查if ($MyObject->hasExtension('ModuleA')) { ... },但是,当然,应用程序不应该知道任何模块。所以我不会以这种方式设计应用程序。

答案 3 :(得分:0)

我建议使用特征(混合)。见PHP reference

答案 4 :(得分:0)

如果你可以在该文件中有另一个类而不是带有函数的文件 - 最好的解决方案是Traits http://php.net/manual/en/language.oop5.traits.php 或使用继承

如果将该代码移到类中,则可以避免大量不必要的代码。我的意思是:

include('additional.functions.php');
$arr = get_defined_functions();
$this->new_Functions = $arr['user'];
// trying to call the function with parameter 10
call_user_func(array($this, $this->new_Functions[0]), 10);

这将是例如:

class myClass extends MyBaseClassWithMyAwesomeFunctions
{
    private $Pvar = 5;
} 

答案 5 :(得分:0)

也许这种方法可以帮助您:

在具有附加功能的文件中,不要定义命名函数,但返回一个闭包,它期望(至少)对象(MyClass的实例)作为参数:

<?php

// additional.functions.php

return function ($myObject) {
    $Object->multiplyPvar($myObject->getTheNumber());
    $Object->doSomethingElse(42, 'foo');
};

构建MyClass的客户端将这些函数从文件收集到数组中:

<?php

$files = [
    '/path/to/my/additional.functions1.php',
    '/path/to/my/additional.functions2.php'
];

$initFunctions = [];
foreach ($files as $path)
    $initFunctions[] = include $path;

$MyObject = new \MyClass($initFunctions);

然后构造函数调用这些函数:

<?php

class MyClass
{
    public function __construct(array $additionalInitFunctions)
    {
        foreach ($additionalInitFunctions as $additionalInitFunction)
            $additionalInitializerFunction($this); // you can also add parameters of course
    }
}

这样,类保持非常好的可测试性以及函数文件。也许这可以帮助你。您永远不应该考虑直接从类外部的任何代码修改对象的内部(私有)状态。这是不可测试的!考虑在实现代码之前编写测试(称为&#34;测试驱动开发&#34;)。您将看到,如果您允许该类之外的任何代码修改类实例的内部(私有)状态,则无法测试类。你不想拥有这个。如果您在不破坏该类的单元测试的情况下更改了类中的某些内部实现细节,那么无论如何您可能会破坏任何additional.functions.php文件中的某些代码,并且没有测试会告诉您:&#34;嘿:您和#39;现在已经破坏了某些东西&#34;。