我正在尝试编写可以动态加载外部函数代码的类代码 用作类的方法。我明白我可以使用扩展和创建 儿童对象,但似乎有一种更简单的方法可以解决这个问题。
关键是要限制必需的代码量 用于执行特定功能。并将所有功能代码保存在单独的文件中 这可能是必需的。
class _DEMO
{
public $_addOn = '';
public function __construct()
{
require_once('DEMOAdd.php');
$this->addOn = addOn;
}
}
在DEMOAdd.php
:
function addOn($_input)
{
return 'getting '.$_input;
}
如何将其加载到_DEMO
类中?以上产生致命错误。
print $_test->addOn('something');
在JavaScript中,可以为变量分配函数。我意识到这一点 不是JavaScript,但我怀疑PHP中有类似的功能。
我也知道PHP中的变量变量,但是我无法围绕这个概念进行思考。
回应这个建议
当另一位开发人员查看您的代码时,不清楚此类的特定角色是什么。相反,他必须检查类中引用的许多文件和外部函数。如果他能看一下班级并且看到“哦,那个班级做到这一点,那就更好”。这甚至是面向对象编程的核心方面。
我同意你的看法。我正在开发一个项目,我是所有东西的唯一开发者,html,javascript,css, 和PHP。我最近一直在使用类定义,但过去编写过很多过程代码。目前 project的代码被分成几个类def文件,因此代码可以在不同的上下文中重用。我的 考虑的是,如果来自网页的查询只需要500行代码,为什么要加载1500行代码来服务 请求。此外,这是一个cms系统,用户数量非常有限(目前只有我),所以音量 交通不是问题。但是如果用户负载较大,则每个用户需要额外的代码,因此需要额外的代码 服务器内存需求显着增加。 cms web界面用于管理直接修改代码的内容 会非常困难。是的,我正在重新发明轮子。 Firestone,General,Nokian等等也是如此。
谢谢大家的答案
我想我的答案可以分配给变量的匿名函数,重新设置php手册
$_var = function($_input)
{
return "getting ".$_input;
}
print $_var('something'); // I have to look back at the manual to varify this line's syntax... yep it looks good.
答案 0 :(得分:0)
使用继承。您可以像这样扩展_DEMO
类:
class _DEMO_ADD extends _DEMO {
...
function addOn(....) {
...
}
请参阅docs on extends
。
答案 1 :(得分:0)
正确设计应用程序
首先。您尝试做的事情违反了清洁面向对象设计的基本方面。为什么即使使用类只是为了调用外部函数?如果你想继续坚持功能编程。
The point is to limit to bare essentials the amount of code that has to be used to perform a particular function. And keep all the function code in separate files that can be required.
良好设计的尝试不仅(仅)您编写的代码量,而是如何实现某项任务。如果一个班级适合解决你的问题,那就使用一个班级。
当另一位开发人员查看您的代码时,不清楚此类的特定角色是什么。相反,他必须检查类中引用的许多文件和外部函数。如果他能看一下班级并且看到“哦,那个班级做到这一点,那就更好”。 这甚至是面向对象编程的核心方面。
好。足够的话题。既然你特别提出这个问题,我会就此提出一些建议尽管我不推荐它,并建议重新考虑你的设计。
动态方法调用
要调用已在其他地方定义的函数,我们将使用魔术方法__call($methodname, $args)
。每当您尝试访问不存在的类方法时,都会调用此方法。
在这个__call()方法中,我们将检查是否存在具有该方法名称的函数,我们试图调用。如果不是,我们可以抛出异常,否则我们将使用call_user_func_array()执行该函数。
<强>的functions.php 强>
<?php
function addOn($input){
echo "This function is procedural and takes the param: " . $input;
}
<强> MyClass.php 强>
<?php
class MyClass{
// This will get called whenever a method on this class
// is called that does not exist
public function __call($name, $args)
{
// Let's check if a function called like the method we wanted
// to call exists somewhere
if(!function_exists($name))
{
// No? So let's raise an Exception
throw new Exception("The function you called " . $name . " does not exist");
}
// Such a function seems to exist so call it and pass
// the arguments
call_user_func_array($name, $args);
}
public function __construct()
{
// Call undefined method
$this->addOn('My Input');
}
}
<强>的index.php 强>
<?php
include 'functions.php';
include 'MyClass.php';
$cls = new MyClass();
答案 2 :(得分:0)
虽然如此,但有一些限制......
<?php
class SomeClass
{
private $_funcs = array();
public function setFunc($name,$func)
{
$this->_funcs[$name] = $func;
}
public function __call($name, $param)
{
if(!function_exists($name))
{
if(isset($this->_funcs[$name]))
$this->_funcs[$name]();
else echo "NO $name <br />";
}
}
public function dummy()
{
echo 'DUMMY<br />';
}
}
然后让我们测试一下:
$sc = new SomeClass();
$sc->haha();
$sc->dummy();
$sc->setFunc('foo',function(){echo 'Hello New World!';});
// blah blah blah...
// blah blah blah...
// blah blah blah...
// blah blah blah...
// blah blah blah...
$sc->foo();
我想到的一个限制是如何确定是否要从$ sc级别返回结果。
结果应该是基于上面的代码:
NO haha
DUMMY
Hello New World!
注意:我知道这不是最好的做法,OP,你应该也知道。我刚刚回答了OP的问题。
编辑:为了能够确定函数是否应该返回某些内容,请尝试利用函数名称(如r_sum)和前缀r_来确定它是否需要返回一些内容。
示例:
public function __call($name, $param)
{
if(!function_exists($name))
{
if(isset($this->_funcs[$name]))
{
if(strpos($name, 'r_')===0)
return $this->_funcs[$name](); // execute and return
else
$this->_funcs[$name](); // just execute
}
else echo "NO $name <br />";
}
}
但是现在,我差点忘了的另一个问题是,你无法通过新的funcs访问类属性。
<强> SUGGESTION 强>
将您的相似或相关功能组合成一个静态类,以便随时随地重复使用您的代码。
//APP contains functions designed closely to work with your CMS
// example
APP::abort();
// HTML contains functions like getting page title, external reso, etc
// example
echo HTML::getTitle();
// ROUTE contains many routing reqs that you may need
// example
ROUTE::to('heaven');
// many more...