简体   繁体   English

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

[英]PHP: Know if instantiation came from static method?

Say I have a class like this: 说我有这样一个类:

class Person
{
    private $value;

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

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

        return $person;
    }
}

How can I keep the constructor from firing, or diverting it in some way to not execute some of itself if I am calling from the static find function? 如果我从静态find函数调用,如何阻止构造函数触发或以某种方式改变构造函数以不执行自身的某些构造?

The context of my example is identical to that of my real code, except the real code has a perfect amount of overhead so long that only one of the functions is ever executed. 我的示例的上下文与我的实际代码相同,不同之处在于,实际代码的开销非常大,以至于只有一个功能可以执行。 (Many objects can exist at the same time, however if the static function calls the __construct method, then there is too much overhead and loading time). (许多对象可以同时存在,但是,如果静态函数调用__construct方法,则开销和加载时间会过多)。

Both need to have public accessors. 两者都需要具有public访问器。

You can pass a boolean into your constructor to tell it whether it should execute or not 您可以将布尔值传递给构造函数以告诉它是否应该执行

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

update using static variable 使用静态变量更新

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

You can make an if statement in your constructor like following 您可以在构造函数中创建一条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;
    }
}

now you can make new Person("old") and leave your overhead or do new Person() and have it... 现在,您可以创建新的Person(“ old”)并留下开销,或者创建新的Person()并拥有它。

If you can't go with @Neysor's idea, because you cannot - what so ever - change the constructor's signature, give this (ugly hack) a shot. 如果您不能接受@Neysor的想法,因为您无法(无论如何)更改构造函数的签名,请尝试一下(丑陋的技巧)。 Bear in mind, that this is something you actually do not want to do in production code. 请记住,这实际上是您不希望在生产代码中执行的操作。 This demo is simply supposed to show that it is indeed possible to use the callstack for conditional execution. 该演示仅被假定为表明确实有可能使用调用堆栈进行条件执行。

<?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)
*/

Although this is possible - DO NOT DO THIS, EVER! 尽管这是可能的-永远不要这样做! If you need to even think about things like these, your API / architecture clearly needs a redesign. 如果您甚至需要考虑这些事情,那么您的API /体系结构显然需要重新设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM