Максим Ворожцов, Плохо, что в текущем варианте приходится высчитывать дату. А если делать просто, то этот расчет на уровне SQL проводится.
Как еще один вариант:
Завести поле (на уровне SQL) в классе Certification date_end
(миграцию применить)
А далее в событии перед сохранением ее высчитывать
class Certification extends ActiveRecord...
{
public function getReverseEndDate(): string
{
//Мне кажется плюс должен быть, если я правильно понимаю смысл
$date = date_create($this->date_from);
$date = date_modify($date, '+'.$this->category->duration_months.'month');
return Yii::$app->formatter->asTimestamp($date);
}
//Перед сохранением считаем эту дату исходя из категории
public function beforeSave($insert)
{
$this->date_end = $this->getReverseEndDate()
return parent::beforeSave($insert);
}
}
$nowDate = date('Y-m-d');
$certifications = Certification::find()
->joinWith(['user', 'profile'])
->andWhere([User::tableName().'.status' => User::STATUS_ACTIVE])
//Применяем фильтр по полям даты начала и конца
->andWhere(['<=', 'date_from', $nowDate])
->andWhere(['>=', 'date_end', $nowDate])
->andWhere('CONCAT_WS(" ", '.Profile::tableName().'.last_name, '.Profile::tableName().'.name, '.Profile::tableName().'.middle_name) LIKE :search')
->params([':search' => '%' . $search . '%'])
->orderBy([Profile::tableName().'.last_name' => 'SORT_ASC', Profile::tableName().'.name' => 'SORT_ASC'])
->limit(8)
#->isValid() //?? метод из модели CertificationQuery уже не нужен
->all();
duck_nukem,
getdate[0] Вернет Вам int 1234568790
а date('YmdHis') вернет string "20171003165103"
"YmdHis" - формат представления даты
Сортировка по имени будет одновременно сортировкой по дате.
Все логи именно так и пишутся. Для директорий принцип абсолютно тот же.
Если мы делаем ArrayHelper, то экземпляр будет работать с определенным массивом. А функции для работы с массивами могут принимать как один, так и два, так и более. Тот же array_merge к примеру. Или strcasecamp для работы со строками.
Исходя из Вашей логики с экземпляром удобно будет работать, если параметр у реализуемых функций будет один. Будет реализован статический класс BaseArrayHelper, который может работать с несколькими массивами и содержать статические методы, и наследник ArrayHelper, который работает только с одним через экземпляр. Но это уже тема типизации и совсем отходит от темы хелперов. В таком случае придется написать много кода-обертки, чтобы обернуть стандартные функции - такое будет полезно, если только времени вагон.
Decadal,
Это я знаю. В этом случае встанет вопрос с автоинкрементом, который мне нужен. По умолчанию в моем случае он создается.
Насчет addPrimaryKey я так не уверен. Этим методом я пользуюсь только в случае составного первичного ключа. Для кросс-таблиц к примеру.
EVOSandru6:
По поводу трейтов, скажу, как сделано у меня.
Есть GiiModel - модель сгенерированная без связей. Я ее не изменяю.
Но от нее наследуется ChildModel и там уже определяю связи, геттеры и прочее. В этих же моделях определяю приватный массив [[$this->_rules]]
Также у меня есть RulesTrait, который содержит метод rules(), и он "мерджить" массив правил из GiiModel и правила, объявленные в приватном свойстве унаследованной модели ChildModel.
Подключая RulesTrait, я переопределяю метод rules() из GiiModel и получаю нужный мне массив для валидации. То есть, определения правил валидации сводятся к их "дополнению".
У такового подхода есть минус один, в свойстве [[$this->_rules]] нельзя указать какое либо выражение, если правила зависят, например от сценария, либо содержат анонимку, то такой подход не подойдет. Хотя, мне кажется, можно и из этого "вывернуться"
Как еще один вариант:
Завести поле (на уровне SQL) в классе Certification
date_end
(миграцию применить)
А далее в событии перед сохранением ее высчитывать