@unfapable

Как нужно сохранять состояние объекта?

Наверное, названия вопроса трудно что-то понять, попытаюсь объяснить, чтобы было понятно.

Стояла задача сделать проверку на вхождение текущего IP в список исключений. Это делается просто вызовов статического метода (IpAddressExclusion::isExcluded), который пробегается по свойству-массиву IP (задан жестко в классе, плохо, но сейчас не в этом суть), и смотрит есть ли текущий IP юзера в этом массиве. Но проблема в том, что этот вызов метода вызывается на странице несколько раз и сейчас выходит так, что каждый раз делается такая же самая проверка, пусть даже она уже проводилась, а это ведь плохо?

Например, есть вызов этого метода в шапке сайта, потом в сайдбаре, а затем в футере - соответственно, если проверка выполнилась в шапке, то нет смысла делать её в сайдбаре и футере, а нужно просто вернуть сохраненное состояние (то есть лог. значение, которое сохранилось в свойстве при первой проверке в шапке)? Если так, то как это грамотно сделать? Правильно ли я понимаю, здесь нужен синглтон? Т.е. в методе isExcluded нужно сохранять состояние проверки и потом проверять если это свойство не null, то возвращать его? Но тогда получится что-то типа такой конструкции: IpAddressExclusion::getInstance()->isExcluded()? Это нормально, смущает что метод getInstance получается статическим, хотя не должен ведь?

Надеюсь понятно что я хочу, новичок ещё, но очень хочется сделать по-нормальному, поэтому всё так расписал :/
  • Вопрос задан
  • 301 просмотр
Решения вопроса 1
rpsv
@rpsv
делай либо хорошо, либо никак
getInstance - это экземпляр объекта (он тоже нужен), и он как раз таки должен быть статическим:
$a = MyClass::getInstance();
$b = MyClass::getInstance();

'a' и 'b' - будут иметь один и тот же объект.
---
Чтобы сохранялось свойство надо примерно такой код:
class C
{
	private $p;

	public function getProperty() {
		if (is_null($this->p)) {
			$this->p = ...
		}
		return $this->p;
	}
}

---
Реализация синглтона в простеньком виде:
class C
{
	private static $instance;

	private function __constructor() {
		// init
	}

	public static function getInstace() {
		if (is_null($this->instance)) {
			$this->instance = new self();
		}
		return $this->instance;
	}
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
DieZz
@DieZz
Вы вызываете статический метод класса, по этому синглтон тут неуместен, поскольку синглтон возвращает объект, а статический метод указывает на класс. Да и пробежаться по массиву и найти есть ли там IP не затратная операция. PHP достаточно шустро работает с массивами. По мне это оптимизация ради оптимизации.

upd:
class IpAddressExclusion
{
    static private $instance;
    private $cache;
    private $excluded = [
        '192.168.1.1',
        '192.168.1.2',
        '192.168.1.3',
    ];

    private function __construct()
    {

    }

    private function setCache($key, $value)
    {
        if (!isset($this->cache[$key])) {
            $this->cache[$key] = $value;
        }
    }

    private function getCache($key)
    {
        if ($this->hasCache($key)) {
            return $this->cache[$key];
        }

        return null;
    }

    private function hasCache($key)
    {
        return isset($this->cache[$key]);
    }

    public function isExcluded($ip)
    {
        $search = array_search($ip, $this->excluded);
        if ($search && $search !== 0) {
            if ($this->hasCache($ip)) {
                return $this->getCache($ip);
            } else {
                $this->setCache($ip, true);
            }

            return true;
        }

        return false;
    }

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new IpAddressExclusion();
        }

        return self::$instance;
    }
}


Тогда использовать так:
if (IpAddressExclusion::getInstance()->isExcluded('192.168.1.1')) {
    //Делам что то
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы