Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP isset($this)并在静态和对象上下文中使用相同的对象方法_Php_Oop_Static_Scope_Isset - Fatal编程技术网

PHP isset($this)并在静态和对象上下文中使用相同的对象方法

PHP isset($this)并在静态和对象上下文中使用相同的对象方法,php,oop,static,scope,isset,Php,Oop,Static,Scope,Isset,我正在研究一个需要通过静态函数调用和对象方法访问的类。我发现的一件事是,我正在跨多个函数复制逻辑 简化示例: class Configurable{ protected $configurations = array(); protected static $static_configurations = array(); public function configure($name, $value){ // ...lots of validat

我正在研究一个需要通过静态函数调用和对象方法访问的类。我发现的一件事是,我正在跨多个函数复制逻辑

简化示例:

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

        }

    }
我还需要静态功能,以便在整个应用程序中设置配置。另外,这种技术的好处是,我可以在两个作用域中使用相同的方法名


这样的测试范围有什么问题吗?性能问题、前向兼容性问题等等。我在PHP5.2上都可以使用,我不需要支持第二种方法的问题是,当错误报告设置为
E\u STRICT
时,它将导致错误。例如:

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) { ... }
}
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;
    }
}
严格标准:第10行的/home/yacoby/dev/php/test.php中不应静态调用非静态方法Foo::bar()

PHP6的一个要点是,E_STRICT错误被移动到E_ALL。换句话说,E_ALL将覆盖所有错误,包括不允许静态调用非静态方法


另一种方法是将验证逻辑移动到静态函数。通过这种方式,非静态函数和静态函数可以调用验证逻辑。

静态方法需要的参数数量与它们的目标对应方不同-额外的参数将是执行上下文。如果没有执行上下文,那么静态调用它才有意义

我的首选方法是创建一个静态类和一个动态类。让一个代理处理对另一个的调用。例如:

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) { ... }
}
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
中填充它,或者跟踪该数组中的所有
DynamicClass
属性,以便您可以快速轻松地传递它


虽然实际上看起来您可能会从单例设计模式中受益。从我所看到的,您正在尝试创建一个全局
可配置的
,并且还可以选择创建单个本地
可配置的
类。使用单例设计模式,您可以创建一个可以访问的全局版本的类arantee您只有其中之一(不违反OOP设计原则,也不必依赖$u GLOBALS等)。例如:

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) { ... }
}
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()访问同一个实例
。您还可以选择创建一次性的非单例版本。实际上,您可以充分利用这两个方面的优势,而只需编写所有方法,并专门考虑动态访问。

我认为允许对实例调用方法和静态调用方法并不是那么荒谬。我的案例:

   TestRecord::generateForm(); // Generate an empty form.

   $test = new TestRecord( $primaryKey );
   [...]
   $test->generateForm();      // Generate an edit form with actual $test values.
我的课程的静态部分涉及空白/新逻辑, 而实例端意味着使用了实时数据

PHP5.3允许通过使用
\uuuu call
\uuuu 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.
  }
}

注意:之所以使用
静态::
后期绑定限定符,是因为我的3个操作方法(
createFields
fillFields
rendrormo
)在这个类的子类中实现为
受保护的
,它是
抽象的
。这是可能的,因为PHP允许受保护的成员在两个方向上访问:从基类到子类,但也从子类到超类。据我所知,这与其他OO语言不同。

如同在核心PHP中一样,我们使用
index.php?var=
,那么在oop php中做同样的事情,我们应该使用什么。

好的,除了严格的错误之外,第二种方法是否有任何问题?我可能会根据您的建议进行更改,但我想了解使用这样的代码的真正问题。这是一种可能从未来的php版本中删除的功能吗r您总是能够静态地调用非静态方法吗?
E\u STRICT
错误往往是“这似乎是一个非常糟糕的主意,但无论如何我们都会让您尝试这样做。”无法保证这样的东西会一直运行,但在完全弃用之前,它们可能会转换为
E_NOTICE
E_WARN
。感谢您的澄清@MightyE@Yacoby如何在静态fn中进行验证?必须不使用
isset($this)
因为
$this
从静态fn中永远不可用,所以您还可以怎么做?