PHP:知道实例化是否来自静态方法?

时间:2012-02-23 18:40:14

标签: php static constructor instantiation

说我有这样的课程:

class Person
{
    private $value;

    public function __construct()
    {
        $this->value = 'new';
    }

    public static function find( $ident )
    {
        $person = new Person();
        $person->value = 'old';

        return $person;
    }
}

如果我从静态find函数调用,如何阻止构造函数触发或以某种方式转移它以不执行某些操作?

我的示例的上下文与我的实际代码的上下文相同,除了真实代码具有完美的开销量,只要执行其中一个函数。 (许多对象可以同时存在,但是如果静态函数调用__construct方法,则会有太多的开销和加载时间。)

两者都需要public个访问者。

3 个答案:

答案 0 :(得分:3)

您可以将布尔值传递给构造函数,告诉它是否应该执行

class Person
{
    private $value;

    public function __construct($exec)
    {
        if(!$exec)
            return;
        $this->value = 'new';
        echo $this->value;  //testing
    }

    public static function find( $ident )
    {
        $person = new Person(false);
        $person->value = 'old';

        return $person;
    }
}

//$p = new Person(true);
$p = Person::find(0);

使用静态变量更新

class Person
{
    private $value;
    protected static $exec1 = true;

    public function __construct()
    {
        if(!self::$exec1)
            return;
        $this->value = 'new';
        echo $this->value;
    }

    public static function find( $ident )
    {
        self::$exec1 = false;
        $person = new Person();
        self::$exec1 = true;
        $person->value = 'old';

        return $person;
    }
}

$p = Person::find(0);

答案 1 :(得分:2)

您可以在构造函数中创建if语句,如下面的

class Person
{
    private $value;

    public function __construct($val)
    {
        $this->value = empty($val)?"new":$val;
        if($this->value == "new") {
          //call function to do more
        }
    }

    public static function find( $ident )
    {
        $person = new Person("old");
        return $person;
    }
}

现在你可以创建新的Person(“old”)并留下你的开销或做新的Person()并拥有它......

答案 2 :(得分:2)

如果你不能按照@Neysor的想法去做,因为你不能 - 这么做 - 改变构造函数的签名,给这个(丑陋的黑客)一个机会。请记住,这是您在生产代码中实际上不想做的事情。这个演示只是表明确实可以使用callstack进行条件执行。

<?php

class Dummy {
    public $was_static = null;

    public function __construct() {
        $this->was_static = false;

        // get current call stack
        $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        // remove __construct() from stack
        array_shift($stack);
        if ($stack) {
            if ($stack[0]['class'] == __CLASS__) {
                // parent function in stack is a function of Dummy
                $this->was_static = true;
            } elseif ($stack[0]['class'] && is_subclass_of($stack[0]['class'], __CLASS__)) {
                // class the function is part of is a descendent of this class
                $this->was_static = true;
            }            
        }
    }

    public static function make() {
        return new self();
    }
}

class Dummy2 extends Dummy {
    public static function make2() {
        return new self();
    }
}

$d = new Dummy();
var_dump($d->was_static);
$d = Dummy::make();
var_dump($d->was_static);
$d = Dummy2::make2();
var_dump($d->was_static);

/*  OUTPUT:

    bool(false)
    bool(true)
    bool(true)
*/

虽然这是可能的 - 不要这样做,永远!如果你甚至需要考虑这些事情,你的API /架构显然需要重新设计。