myks92
@myks92
Нашёл решение — пометь вопрос ответом!

Как в Active Query применить метод из модели?

Доброй ночи всем!

Очень давно задавал вопрос на похожую тему: Active Query как применить функцию из модели?, но так и не решил этот момент для себя. Вроде бы ответы правильные, но задал вопрос не правильно, поэтому не получил должного ответа. Теперь задаю его снова.

Запрос:
$certifications = Certification::find()
            ->joinWith(['user', 'profile'])
            ->andWhere([User::tableName().'.status' => User::STATUS_ACTIVE])
            ->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();


Модель Active Query (CertificationQuery)
public function isValid()
    {
        $this->andWhere(['<=',  'date_from',  'здесь рассчитываемая из модели обратная дата (getReverseEndDate())']);
    }


Метод и модели Certification, который нужно применить
/**
     * Получаем обратную дату окончания действия категории
     * @return string
     */
    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);
    }


Вопрос:
  1. Как я могу применить метод getReverseEndDate() из модели в Active Query?
  2. Поправьте, если я не правильно рассчитываю дату. Мне нужно прибавлять месяцы.


Обращаю внимание, что метод находится в модели, с помощью который делаем запрос. Благодарю!
  • Вопрос задан
  • 100 просмотров
Решения вопроса 1
Я бы в модель добавил дополнительную связь по валидной дате:
class Certification extends ActiveRecord...
{
//...

/**
* Получаем обратную дату окончания действия категории
* @return string
*/
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 getValidCategory()
{
    return $this->hasOne(Category::className(), ['id' => 'category_id'])
        ->andWhere(['<=',  'date_from',  'reverseEndDate']);
}


А затем бы JOIN (join with valid category) по этой связи.
NULL отсеются автоматом
$certifications = Certification::find()
            ->joinWith(['user', 'profile', 'validCategory'])
            ->andWhere([User::tableName().'.status' => User::STATUS_ACTIVE])
            ->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();
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
VladimirAndreev
@VladimirAndreev
php web dev
передайте в ActiveQuery экземпляр модели. там что-то из $this берется, так что простой (new Certification())->getReverseEndDate() не подойдет.

а вообще, имхо, в моделях логики быть не должно, вся логика должна быть в их Query...
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы