PHP: Знаете ли вы, что создание экземпляра происходит от статического метода? - PullRequest
2 голосов
/ 23 февраля 2012

Скажем, у меня есть такой класс:

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 ]

3 голосов
/ 23 февраля 2012

Вы можете передать логическое значение в конструктор, чтобы сообщить ему, должно ли оно выполняться или нет

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);
2 голосов
/ 23 февраля 2012

Если вы не можете согласиться с идеей @ Neysor, потому что вы не можете - что бы то ни было - изменить подпись конструктора, сделайте это (безобразный хак) выстрел. Имейте в виду, что это то, что вы на самом деле не хотите делать в рабочем коде. Предполагается, что эта демонстрация просто показывает, что действительно возможно использовать стек вызовов для условного выполнения.

<?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 / архитектура явно нуждается в редизайне.

2 голосов
/ 23 февраля 2012

Вы можете сделать оператор 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;
    }
}

теперь вы можете создать нового персонажа ("старого") и оставить свои накладные расходы или создать нового персонажа () и получить его ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...