#php #oop #static
#php #ооп #статический
Вопрос:
Я пишу класс PHP и включил пару статических функций для быстрого доступа, поскольку они обычны в использовании и просты в функционировании. Однако они используют объект в них для доступа к базе данных. Скорее всего, я буду использовать эти статические методы как из статического, так и из нестатического контекста во всем своем коде, поэтому я хочу иметь возможность проверить, была ли функция вызвана из статического или нестатического контекста, чтобы я мог избежать создания дублирующего объекта, если функция была вызвана из нестатического контекста (этот экземпляр объекта и тот, который внутри функции будет использоваться статически). Есть ли какой-либо способ, которым я могу протестировать это в функции, чтобы я мог использовать объект экземпляра, если функция вызывается из нестатического контекста, и создать свой собственный объект, если функция вызывается из статического контекста?
Пример кода:
class MyClass {
private $db;
function __constuct(){
$this->db = new DBConnect();
}
public static function myFunction(){
if(/* Is static */){
$db = new DBConnect();
} else {
$db =amp; $this->db;
}
// Do processing with $db, etc.
}
}
Комментарии:
1. 5 ответов, ни одного голоса за вопрос.
Ответ №1:
Когда метод объявлен как статический, не только недоступна магическая переменная $this (возвращает NULL), но и невозможно определить, действительно ли функция была вызвана из статического контекста. Обратная трассировка подразумевает, что для статического метода вызов $object->method() внутренне преобразуется в className::method() во время выполнения.
Комментарии:
1. Спасибо за это, Шакти, это отвечает на мой вопрос. Мне просто нужно будет создать объект для каждого из статических методов внутри, если я захочу использовать их из статического контекста.
2. Или кажется, что я мог бы просто объявить
$db
переменную экземпляра как статическую. Использованиеprivate static
для чего-то просто кажется мне странным.
Ответ №2:
Вы можете проверить наличие нестатического доступа, только если вы не заставляете метод быть только статическим. Исключите static
ключевое слово из объявления функции и протестируйте с:
public function myFunction(){
if(!isset($this)) {
(Она все еще может вызываться как статическая функция, даже если вы не объявляли ее как таковую.)
Комментарии:
1. Не приводит ли статический доступ к функции без ключевого слова static к ошибке?
2. Это действительно генерирует уведомление или предупреждение E_STRICT (не уверен в классификации). По крайней мере, в той версии, которая у меня есть. (Эти вещи, как правило, иногда устаревают и не рекомендуются.)
Ответ №3:
Итог — не создавайте классы, которые содержат только статические функции. Это не ООП, это просто ваш старый процедурный код, маскирующийся под ооп
Если вы выполняете функции статически, $ this отсутствует, поскольку нет объекта. В конечном итоге вы также создадите private $db
статическую переменную и будете использовать ее как self::$db
.
Тем не менее, я бы рекомендовал отказаться от этого шаблона и написать что-то вроде :
class Foobar
{
protected $_connection = null;
public function __construct( DBConnect $db )
{
$this->_connection = $db;
}
public function some_function()
{
$db = $this->_connection;
// Do processing with $db, etc.
}
}
И вы используете этот класс следующим образом :
$db = new DBConnection( /* your password , user , host , etc. */);
$stuff = new FooBar( $db );
$stuff->some_function();
$blah = new DifferentClass( $db );
Таким образом, вы используете одно и то же соединение со всеми классами, которым это требуется. И теперь класс FooBar
не несет ответственности за установление соединения или должен знать ваши данные о соединении.
Ответ №4:
Решение 1. Сделайте $db
переменную закрытой и используйте ее через средство получения.
Решение 2. Реализуйте одноэлементный шаблон на стороне dbal.
Ответ №5:
Даже при вызове статического метода из экземпляра (не рекомендуется) у вас нет доступа к $this
, поэтому ваш класс будет фатальным.
class sns {
public static function moo() {
var_dump($this->fng);
}
public function goo() {
var_dump($this);
}
}
sns::moo();
$_ = new sns;
$_->moo();
$_->goo();
Как указано в другом постере из руководства по php.
$db
однако вместо этого может быть определено статически, поэтому его нужно создать только один раз, независимо от того, является ли объект экземпляром или нет.