Как избавиться от слишком большого количества операторов в laravel? - PullRequest
0 голосов
/ 28 августа 2018

Я хотел бы создать более читаемый код, исключив слишком много операторов if, но все же выполняя свою работу. Я попытался создать приватный метод, извлечь запрос диапазона дат и вернуть экземпляр построителя, но всякий раз, когда я делаю это, он не возвращает правильный результат запроса построителя, поэтому я в итоге разбиваю все по этому методу.

Другие параметры будут добавлены в ближайшее время, поэтому операторы if будут складываться очень быстро. (

Любой совет о том, как улучшить, будет высоко ценится. Спасибо!

/**
 * @param array $params
 *
 * @param $orderBy
 * @param $sortBy
 *
 * @return Collection
 *
 * Sample:
 * `/orders?release_date_start=2018-01-01&release_date_end=2018-02-20&firm_id=3` OR
 * `/orders?claimId=3&status=completed`
 *
 * Problem: Too many if statements
 *
 */
public function findOrdersBy(array $params, $orderBy = 'id', $sortBy = 'asc'): Collection
{
    $release_date_start = array_get($params, 'release_date_start');
    $release_date_end = array_get($params, 'release_date_end');
    $claimId = array_get($params, 'claimId');
    $firm_id = array_get($params, 'firm_id');
    $status = array_get($params, 'status');

    $orders = $this->model->newQuery();

    if (!is_null($release_date_start) && !is_null($release_date_end)) {
        $orders->whereBetween('releaseDate', [$release_date_start, $release_date_end]);
    } else {
        if (!is_null($release_date_start)) {
            $orders->where('releaseDate', '>=', $release_date_start);
        } else {
            if (!is_null($release_date_end)) {
                $orders->where('releaseDate', '<=', $release_date_end);
            }
        }
    }

    if (!is_null($claimId)) {
        $orders->where(compact('claimId'));
    }

    if (!is_null($firm_id)) {
        $orders->orWhere(compact('firm_id'));
    }

    if (!is_null($status)) {
        $orders->where(compact('status'));
    }

    return $orders->orderBy($orderBy, $sortBy)->get();
}

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Одна опция , которую вы можете использовать - это троичная операция в php:

$claimId ? $orders->where(compact('claimId')) : ;
$firm_id ? $orders->orWhere(compact('firm_id')) : ;
$status ?  $orders->where(compact('status')) : ;

Это будет чище, чем код операторов.

Другая опция , которую вы можете использовать в laravel - Условные предложения

0 голосов
/ 29 августа 2018

Спасибо за ваши предложения, но я нашел другое решение:

/**
 * @param array $params
 *
 * @param $orderBy
 * @param $sortBy
 *
 * @return Collection
 */
public function findOrdersBy(array $params, $orderBy = 'id', $sortBy = 'asc'): Collection
{
    $release_date_start = array_get($params, 'release_date_start');
    $release_date_end = array_get($params, 'release_date_end');

    $orders = $this->model->newQuery();

    if (!is_null($release_date_start) && !is_null($release_date_end)) {
        $orders->whereBetween('releaseDate', [$release_date_start, $release_date_end]);
    } else {
        if (!is_null($release_date_start)) {
            $orders->where('releaseDate', '>=', $release_date_start);
        } else {
            if (!is_null($release_date_end)) {
                $orders->where('releaseDate', '<=', $release_date_end);
            }
        }
    }

    $fields = collect($params)->except($this->filtersArray())->all();
    $orders = $this->includeQuery($orders, $fields);

    return $orders->orderBy($orderBy, $sortBy)->get();
}

/**
 * @param Builder $orderBuilder
 * @param array $params
 *
 * @return Builder
 */
private function includeQuery(Builder $orderBuilder, ... $params) : Builder
{
    $orders = [];
    foreach ($params as $param) {
        $orders = $orderBuilder->where($param);
    }

    return $orders;
}

/**
 * @return array
 */
private function filtersArray() : array
{
    return [
        'release_date_start',
        'release_date_end',
        'order_by',
        'sort_by',
        'includes'
    ];
}

Главный фактор для private method includeQuery(Builder $orderBuilder, ... $params), который принимает $params в качестве аргумента переменной длины . Мы просто перебираем переменные, передаваемые в качестве параметра запроса /orders?code=123&something=test, и передаем их как предложение where() в построителе запросов.

Некоторые параметры могут не являться свойством вашего объекта, поэтому мы должны фильтровать только те параметры запроса, которые соответствуют свойствам объекта. Поэтому я создал filtersArray(), который будет возвращать исключаемые параметры и предотвращать ошибку.

Хммм, на самом деле, при написании этого я должен иметь противоположность, которая only(), иначе он будет иметь бесконечное множество вещей, которые нужно исключить. :) Это был бы еще один рефакторинг : P

0 голосов
/ 28 августа 2018

если вы заинтересованы в использовании методов сбора, то вы можете использовать when() метод сбора, чтобы опустить ваши if-else операторы. Так что по вашему утверждению это будет выглядеть примерно так:

$orders->when(!is_null($release_date_start) && !is_null($release_date_end), function($q) {
    $q->whereBetween('releaseDate', [$release_date_start, $release_date_end]);
}, function($q) {
    $q->when(!is_null($release_date_start), function($q) {
        $q->where('releaseDate', '>=', $release_date_start);
    }, function($q) {
        $q->when(!is_null($release_date_end), function($q) {
            $q->where('releaseDate', '<=', $release_date_end);
        })
    })
})
->when(!is_null($claimId), function($q) {
    $q->where(compact('claimId'));
})
->when(!is_null($firm_id), function($q) {
    $q->orWhere(compact('firm_id'));
})
->when(!is_null($status), function($q) {
    $q->where(compact('status'));
})

Для получения дополнительной информации вы можете увидеть условные предложения в документации. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...