PHP конструктор, вызывающий сам себя — не рекурсия

#php #namespaces

#php #пространства имен

Вопрос:

Я добавляю некоторые модули в PHP-фреймворк, который уже установлен и работает безупречно. Он поддерживает несколько драйверов базы данных. Я смотрю на основную системную логику.

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

Я просмотрел документацию по новому пространству имен PHP и конструктору, и это не устраняет моего замешательства.

Основной код драйвера MySQLi для фреймворка выглядит следующим образом:

 <?php

namespace SimFrSystemLibraryDB;


class MySQLi {
    private $connection;

    public function __construct($hostname, $username, $password, $database, $port = '3306') {
        $mysqli = @new MySQLi($hostname, $username, $password, $database, $port);

        if (!$mysqli->connect_error) {
            $this->connection = $mysqli;
            $this->connection->report_mode = MYSQLI_REPORT_ERROR;

        } else {
            throw new Exception('MySQLi DB Failure');
        }
    }

... rest of class logic ...
 

Мне интересно, как в конструкторе, когда он присваивает переменной ( $mysqli ) собственный объект, он не застревает в рекурсивном цикле.

Является ли мое понимание пространств имен неточным? Спасибо за вашу помощь в понимании.

Комментарии:

1. Да, это ваше понимание пространств имен, которое является неточным. Обратите внимание на обратную косую черту перед MySQLi . Так что это совершенно другой класс

2. Хорошо, я проведу дополнительные исследования по пространствам имен. Однако для MySQLi нет корневого класса пространства имен — поэтому я предположил, что он создал класс на основе текущего класса в корневом пространстве имен. Это неверно?

3. Что это значит: «для MySQLi нет корневого класса пространства имен»? Исходный класс MySQLi находится в корневом пространстве имен, как и все другие встроенные классы PHP. in из имени класса явно означает «корневое пространство имен»

4. я чувствую себя довольно глупо. я понятия не имею, почему это не регистрировалось. Спасибо

5. Что это за строка $this->connection->report_mode = MYSQLI_REPORT_ERROR; ? Это не имеет смысла

Ответ №1:

Является ли мое понимание пространств имен неточным?

Да, но это немного сложно из-за именования. Это:

 namespace SimFrSystemLibraryDB;
class MySQLi { ... }
 

Вызывает вызываемый класс SimFrSystemLibraryDBMySQLi , в то время как это:

 $mysqli = @new MySQLi(...)
 

Ссылается на вызываемый класс MySQLi .

Первая ссылка на класс (определение) не имеет ведущей косой черты, поэтому она помещается в любое текущее пространство имен. Вторая ссылка на класс (создание экземпляра) имеет начальную обратную косую черту, которая явно помещает ее в корневое пространство имен. Итак, у вас есть два класса с одинаковыми именами, но они находятся в разных пространствах имен и, следовательно, являются разными классами.

Комментарии:

1. Как это тогда предотвращает рекурсивный цикл? Он создает класс с той же логикой, которую я предполагаю? Итак, как конструктор не вызывает себя в том же корневом пространстве имен снова?

2. Рекурсивного цикла нет. SimFrSystemLibraryDBMySQLi Конструктор создает экземпляр MySQLi , который является другим классом со своим собственным конструктором.

3. Это встроенный PHP, например DateTime .

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

5. На самом деле «композиция над наследованием» часто пропагандируется как лучший способ проектирования вещей. В этом случае расширение встроенного класса означало бы, что все его методы были доступны по умолчанию, но не интегрированы ни с одной из функций, добавленных оболочкой, что может привести к большой путанице. Использование имени MySQLi для оболочки, возможно, не лучший выбор; возможно, им следовало назвать это MySQLj или что-то в этом роде 😜