PHP конструкторы и статические функции - PullRequest
14 голосов
/ 22 ноября 2011

Я немного запутался в том, как работают конструкторы в PHP.

У меня есть класс с конструктором, который вызывается при создании нового объекта.

$foo = new Foo($args);

__construct($params) вызывается в классе Foo и выполняет соответствующий код инициализации.

Однако, когда я использую класс для вызова статической функции, конструктор вызывается снова.

$bar = Foo::some_function(); //runs the constructor from Foo

Это заставляет конструктор выполняться, выполняя код инициализации объекта, который я предназначил только для создания нового объекта Foo.

Неужели я не понимаю, как работают конструкторы? Или есть способ предотвратить выполнение __construct(), когда я использую класс для выполнения статических вызовов функций?

Должен ли я использовать "фабричную" функцию вместо инициализации объекта? Если да, то в чем смысл конструктора?

:: EDIT :: У меня есть форма, где пользователи могут загружать фотографии в альбом (create_photo.php) и область, где они могут просматривать альбом (view_photos.php). По форме отправьте:

$photo = new Photo($_FILES['photo'], $_POST['arg1'], ect..);

Конструктор Photo создает и сохраняет фотографию. Однако в view_photo.php, когда я звоню:

$photo = Photo::find_by_id($_POST['id']) //user-defined function to query database

Это вызывает запуск конструктора Photo!

Ответы [ 4 ]

20 голосов
/ 22 ноября 2011

Я не вижу ничего похожего на ваш вопрос.

См. Демонстрацию: http://codepad.org/h2TMPYUV

Код:

class Foo {
    function __construct(){ 
        echo 'hi!';
    }
    static function bar(){
        return 'there';
    }
}

echo Foo::bar(); //output: "there"
6 голосов
/ 22 ноября 2011

Успенская PHP 5.x

Разные цели, разные пути

  1. создать новый экземпляр класса (объекта)

    class myClassA
    {
       public $lv;
    
       public function __construct($par)
       {
           echo "Inside the constructor\n";
           $this->lv = $par;
       }
    }
    
    $a = new myClassA(11);
    $b = new myClassA(63);
    

    потому что мы создаем новый объект, который вызывает PHP:

    __construct($par);

    нового объекта, поэтому:

    $a->lv == 11 
    
    $b->lv == 63
    
  2. использовать функцию класса

    class myClassB
    {
        public static $sv;
    
        public static function psf($par)
        {
            self::$sv = $par;
        }
    }
    
    myClassB::psf("Hello!");
    $rf = &myClassB::$sv;
    myClassB::psf("Hi.");
    

    сейчас $rf == "Hi."

    функция или переменные должны быть определены как static для доступа к ::, объект не создается с вызовом "psf", "переменная класса" sv имеет только 1 экземпляр внутри класса.

  3. использовать синглтон, созданный Фабрикой (myClassA выше)

    class myClassC
    {
    
        private static $singleton;
    
        public static function getInstance($par){
    
            if(is_null(self::$singleton)){
    
                self::$singleton = new myClassA($par);
    
            }
    
            return self::$singleton;
    
        }
    
    }
    
    $g = myClassC::getInstance("gino");
    echo "got G\n";
    
    $p = myClassC::getInstance("pino");
    echo "got P\n";
    

Используя фабрику ( getInstance ), мы впервые строим новый объект, для которого $ par установлен в gino .

Использование фабрики во второй раз $ singleton уже имеет значение, которое мы возвращаем. Новый объект не создается (не вызывается __ конструкция , используется меньше памяти и процессора).

Значением курса является объект instanceOf myClassA и не забудьте:

myClassC::$singleton->lv == "gino"

Обратите внимание на синглетоны:

Что плохого в синглетах?

http://www.youtube.com/watch?v=-FRm3VPhseI

Судя по моему ответу, я не хочу рекламировать / понижать синглтон Просто из слов в вопросе я сделал это calc:

"статические" + "__ конструкт" = "синглтон"!

1 голос
/ 25 декабря 2013

Вот мой обходной путь :

Я поместил метод construct() в статический класс.Обратите внимание, что он отличается от __construct(), который я использую в обычных классах.

Каждый класс находится в отдельном файле, поэтому я лениво загружаю этот файл при первом использовании класса.Это дает мне событие первого использования класса.

spl_autoload_register(function($class) {

    include_once './' . $class . '.php';

    if (method_exists($class, 'construct')) {
        $class::construct();
    }
});
0 голосов
/ 18 мая 2018

Я определяю свойства класса как массив в статическом методе и вызываю их через метод. Я не уверен, что это лучшее решение или нет, но прекрасно работает.

Пример:

    class Foo
    {
      private static construct_method()
      {
        return [
          'one' => 1,
          'two' => 2
        ];
      }

      public static any_method()
      {
        return self::construct_method()['one'] + self::construct_method()['two'];
      }

    }

    echo Foo::any_method(); // 3
...