我正在研究一个需要通过静态函数调用和对象方法访问的类。我发现的一件事是我在多个函数中复制逻辑。
简化示例:
class Configurable{
protected $configurations = array();
protected static $static_configurations = array();
public function configure($name, $value){
// ...lots of validation logic...
$this->configurations[$name] = $value;
}
public static function static_configure($name, $value){
// ...lots of validation logic (repeated)...
self::$static_configurations[$name] = $value;
}
}
我找到了解决方法,但感觉很脏:
class Configurable{
protected $configurations = array();
protected static $static_configurations = array();
public function configure($name, $value){
// ...lots of validation logic...
if (isset($this)){
$this->configurations[$name] = $value;
}
else{
self::$static_configurations[$name] = $value;
}
}
}
我也需要静态功能,以便我可以在整个应用程序中设置配置。此外,这种技术的好处是我可以在两个范围中使用相同的方法名称。
这样的测试范围有问题吗?性能问题,前向兼容性问题等。它在PHP 5.2上都适用于我,我不需要支持< 5。
答案 0 :(得分:2)
第二种方法的问题是,当错误报告设置为E_STRICT
时,它将导致错误。例如:
严格标准:非静态方法Foo :: bar()不应在第10行的/home/yacoby/dev/php/test.php中静态调用
PHP6的一点是E_STRICT错误被移动到E_ALL。换句话说,E_ALL将涵盖所有错误,包括不允许您静态调用非静态方法。
另一种方法可能是将验证逻辑移动到静态函数。这样非静态函数和静态函数就可以调用验证逻辑。
答案 1 :(得分:2)
静态方法需要的参数数量与其目标对应项不同 - 附加参数将是执行上下文。如果没有执行上下文,那么只有 才能静态调用它。
我的首选方法是,我正在构建一个具有多个这样的接口的库,就是创建一个静态类和一个动态类。让一个代理呼叫另一个。例如:
class DynamicClass {
protected $foo;
protected $bar;
public function baz($arg1) {
return StaticClass::bar($this->foo, $arg1);
}
public function zop($arg1, $arg2) {
return StaticClass::zop($this->foo, $this->bar, $arg1, $arg2);
}
// Context-less helper function
public function womp($arg1) {
return StaticClass::womp($arg1);
}
}
class StaticClass {
public static function baz(&$fooContext, $arg1) { ... }
public static function zop(&$fooContext, &$barContext, $arg1, $arg2) { ... }
public static function womp($arg1) { ... }
}
由您决定如何将上下文传递给静态类 - 您必须为您做任何有意义的事情。在大多数函数中完成的工作应该非常小(如果你做了很多,那么你可能应该将工作分解为更小的函数),因此只需要一些上下文参数。或者您可以创建一个完整的上下文数组并将其传递到任何地方(在每次调用之前将其填充到DynamicClass
中,或者跟踪该数组中的所有DynamicClass
属性,以便您可以快速且轻松地传递它周围。
虽然看起来你可能会受益于Singleton设计模式。从我所看到的,您正在尝试创建全局Configurable
,并且还可以选择创建单独的本地Configurable
。使用单例设计模式,您可以创建一个全局可访问的类,您可以保证只有一个类(不破坏OOP设计原则,不得不依赖$ _GLOBALS等)。例如:
class DynamicClass {
protected $foo;
protected $bar;
public function baz($arg1) { ... }
public function zop($arg1, $arg2) { ... }
public static function getSingleton() {
static $instance = null;
if ($instance === null) $instance = new DynamicClass();
return $instance;
}
}
无论您的代码位于何处,都可以使用DynamicClass::getSingleton()
访问同一个实例。您还可以选择创建一次性非单例版本。您基本上可以充分利用这两个世界,同时只需要考虑动态访问权限就可以编写所有方法。
答案 2 :(得分:2)
我不觉得允许在一个实例上调用一个方法也是非常荒谬的。我的情况:
TestRecord::generateForm(); // Generate an empty form.
$test = new TestRecord( $primaryKey );
[...]
$test->generateForm(); // Generate an edit form with actual $test values.
我班级的静态方面处理空白/新逻辑, 实例端表示使用实时数据。
PHP 5.3允许使用__call
,__callStatic
和static::
实现此目的:
public function __call( $name, $args )
{
if ( $name == 'generateForm' ) {
$this->fields = static::createFields(); // Action 1 : static.
$this->fillFields(); // Action 2 : instance.
static::renderForm( $this->fields ); // Action 3 : static.
}
}
public static function __callStatic( $name, $args )
{
if ( $name == 'generateForm' ) {
$fields = static::createFields(); // Action 1 : static.
// Action 2 : none.
static::renderForm( $fields ); // Action 3 : static.
}
}
注意:使用了static::
后期绑定限定符,因为我的3个操作方法(createFields
,fillFields
和rendreForm
)被实现为protected
在此类的子类中abstract
。{{1}}。这是可能的,因为PHP允许受保护的成员在两个方向上访问:从基类到子类,但也从子类到超类。据我所知,这与其他OO语言不同。
答案 3 :(得分:-1)
在核心php我们使用<script>
function do_check()
{
var return_value=prompt("Password:");
if(return_value==="your_password")
return true;
else
return false;
}
</script>
<form action="log.php" method="post" onsubmit="return do_check();">
,所以在oop php中做同样的事情我们应该使用什么。