Можно ли создавать статические классы в PHP (например, в C#)?

Я хочу создать статический класс в PHP и заставить его вести себя так же, как в C#, поэтому

  1. Конструктор автоматически вызывается при первом вызове класса
  2. Создание экземпляра не требуется

Что-то в этом роде ...

static class Hello {
    private static $greeting = 'Hello';

    private __construct() {
        $greeting .= ' There!';
    }

    public static greet(){
        echo $greeting;
    }
}

Hello::greet(); // Hello There!

Не могли бы вы вкратце объяснить, как должен вести себя статический класс? Это реализация утилиты?

xtofl 22.01.2009 14:04

Просто высказываю свое собственное мнение, но, исходя из моего опыта работы с PHP, для здравомыслия, тестируемости и масштабируемости статические классы должны в значительной степени полностью не иметь состояния, представлять более функциональный API-интерфейс, подобный программированию, чем объектно-ориентированный, и, как правило, лучше всего использовать в качестве фасадов доступности для полностью созданных объектов или служебных оболочек для помощников или аналогичных конструкций, если они вообще используются.

mopsyd 27.10.2017 06:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
142
2
114 877
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

У вас могут быть статические классы в PHP, но они не вызывают конструктор автоматически (если вы попытаетесь вызвать self::__construct(), вы получите сообщение об ошибке).

Поэтому вам нужно будет создать функцию initialize() и вызывать ее в каждом методе:

<?php

class Hello
{
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>

Я довольно часто делаю это, просто чтобы собрать все функции в одном месте. IE Utility :: doSomethingUseful ();

smack0007 22.01.2009 13:57

Вместо Therefore you'd have to create an initialize() function and call it in each method: было бы проще сделать initialize общедоступной функцией и вызывать ее сразу после объявления класса.

chacham15 15.04.2013 06:00

Я знаю, что это довольно давно, но теперь вы можете использовать магию __callStatic, поэтому, когда вы вызываете какой-либо статический метод или что-то еще, он сначала вызывает __callStatic, там вы можете увидеть, инициализирован ли он, а затем выполнить self::$method или что-то еще, что вы вызываете. Если он по-прежнему вызывает метод напрямую, попробуйте изменить все на частное и посмотрите там.

matiaslauriti 06.10.2017 00:37

Что произойдет, если два потока вызовут приветствие одновременно? Поскольку нет синхронизации, инициализация не будет вызываться дважды (что в этом случае нормально, но во многих других случаях - нет). Или php однопоточный и не вытесняющий, как node?

John Little 21.11.2017 16:40

Мне понравилось, как вы это сделали. Фантастический.

SaurabhCooks 25.03.2021 14:27

у вас могут быть эти «статические» классы. но я полагаю, что чего-то действительно важного не хватает: в php у вас нет цикла приложения, поэтому вы не получите настоящую статику (или синглтон) во всем приложении ...

см. Синглтон в PHP

Статические классы и синглтоны - это всего лишь две разные вещи.

Max Cuttins 29.08.2019 02:11
final Class B{

    static $staticVar;
    static function getA(){
        self::$staticVar = New A;
    }
}

структура b называется обработчиком single, вы также можете сделать это в

Class a{
    static $instance;
    static function getA(...){
        if (!isset(self::$staticVar)){
            self::$staticVar = New A(...);
        }
        return self::$staticVar;
    }
}

это одноэлементное использование $a = a::getA(...);

объект не может быть определен статически но это работает

final Class B{
  static $var;
  static function init(){
    self::$var = new A();
}
B::init();

Андреас Нидермайр: вот как работает php (app-cycle = одиночный запрос). Но синглтон (на том, который находится в запросе) - это возможность в php (в php синглтон - это объект, имеющий 1 экземпляр (внутри приложения- цикл)

borrel 09.12.2010 13:43

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

По моему скромному мнению, это более полный пример, основанный на примере Грега:

<?php

class Hello
{
    /**
     * Construct won't be called inside this class and is uncallable from
     * the outside. This prevents instantiating this class.
     * This is by purpose, because we want a static class.
     */
    private function __construct() {}
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>

Это отличный подход, однако функция построения не может быть реализована, если ваш одиночный элемент наследуется от определенных объектов, которым требуется общедоступный конструктор.

Eric Herlitz 15.12.2013 21:40

@EricHerlitz Этот вопрос не о синглтонах, а о статических классах. Зачем вам создавать статический класс, наследующий от класса, который должен быть создан?

Mark Amery 06.03.2014 19:22

В равной степени объявление класса как абстрактного с предотвращением его создания экземпляров и по-прежнему разрешает вызовы статических методов.

bstoney 15.04.2015 06:28

Обычно я предпочитаю писать обычные нестатические классы и использовать фабричный класс для создания отдельных (sudo static) экземпляров объекта.

Таким образом, конструктор и деструктор работают как обычно, и я могу создавать дополнительные нестатические экземпляры, если хочу (например, второе соединение с БД)

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

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

class Factory {
    static function &getDB ($construct_params = null)
    {
        static $instance;
        if ( ! is_object($instance) )
        {
            include_once("clsDB.php");
            $instance = new clsDB($construct_params);   // constructor will be called
        }
        return $instance;
    }
}

Класс БД ...

class clsDB {

    $regular_public_variables = "whatever";

    function __construct($construct_params) {...}
    function __destruct() {...}

    function getvar() { return $this->regular_public_variables; }
}

Везде, где вы хотите его использовать, просто позвоните ...

$static_instance = &Factory::getDB($somekickoff);

Затем просто рассматривайте все методы как нестатические (потому что они есть)

echo $static_instance->getvar();

На самом деле это реализация одноэлементного шаблона, и ее на самом деле не следует использовать - вместо этого используйте внедрение зависимостей, которое можно тестировать и упрощает отладку.

Thomas Hansen 29.08.2014 11:40

Можете ли вы привести пример того, как использовать инъекцию зависимостей для этого ответа и как это сделать его более тестируемым?

cjsimon 24.04.2018 02:09

Другие вопросы по теме