#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 или что-то в этом роде 😜