Предположим, у меня есть модель со свойством:
/**
* @var array
*/
protected $myProperty;
Для этого свойства нет поля базы данных, данные для этого свойства извлекаются откуда-то еще:
/**
* @return array
*/
public function getMyProperty() {
return getDataFromSomewhere();
}
Проблема, которую я вижу здесь, заключается в том, что если я использую это свойство более одного раза, функция вызывается несколько раз. И если эта функция извлекает данные, например, из другой таблицы с mysql объединяется или выполняет некоторые обширные вычисления, это неэффективно.
Какие у меня здесь возможности? Немного улучшить геттер?
/**
* @return array
*/
public function getMyProperty() {
if ($this->myProperty === NULL) {
$this->setMyProperty(getDataFromSomewhere());
}
return $this->myProperty;
}
Я знаю, что могу использовать Caching Framework и кэшировать значение, возвращаемое функцией getDataFromSomewhere, но я ищу более простое решение.
Вы можете сделать так, чтобы метод получения работал с return $this->myProperty ?? ($this->myProperty = getDataFromSomewhere());
. Затем он заполняет локальное свойство перед возвратом значения, если оно равно нулю - вы, конечно, убедитесь, что свойство инициализировано как.
Это просто более короткая форма моего метода получения, не так ли? Я все еще предпочитаю свой метод получения, потому что я сравниваю свойство с NULL (0, -1, false и т. д. Могут быть допустимыми значениями для свойства), и я думаю, что лучше использовать метод установки.
Оператор ??
называется оператором объединения с нулевым значением, потому что он запускает часть «else» только в том случае, если значение переменной точно равно нулю (не ложно, не пусто, а равно нулю). Он делает то, что вам нужно, без необходимости писать оператор if-then. Сохраняет ваш метод получения только в одну строку.
Что касается вызова метода установки, на мой взгляд, неправильная логика иметь метод получения вызова метода установки. Вы на самом деле не устанавливаете свойство, вы его «размораживаете». Таким образом, внутренняя операция, не вызывающая методов.
Второй вариант метода получения, который вы предлагаете, является хорошей идеей и обычно известен как «ленивая загрузка». Поле myProperty
заполняется данными только при доступе к нему. С другой стороны, если метод-получатель никогда не вызывается, данные вообще не нужно загружать.
Вы можете выбрать другой стиль кодирования, например, с использованием тройной- или нулевые операторы объединения, но схема остается той же. Вы можете найти больше примеров своей идеи в сети.
совершенно другой подход заключался бы в том, чтобы выполнять выборку и вычисления с использованием cronjob и записывать отображаемое значение в столбец базы данных.