简体   繁体   中英

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?

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

Both need to have public accessors.

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

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...

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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