Code Duplication in Laravel ORM

Asked

Viewed 53 times

1

I was working and came across the following situation:

if (($entrada == null) and ($parcela == null)) {
    $cotas = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))
        ->get();
} elseif ($parcela == null) {
    $cotas = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))
        ->where('entrada', '<=', Utils::calculaPorcentagem($porcentagem, $entrada))
        ->get();
} elseif ($entrada == null) {
    $cotas = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))
        ->whereHas('saldo', function ($query) use ($parcela, $porcentagem) {
            $query->where('parcela', '<=', Utils::calculaPorcentagem($porcentagem, $parcela));
        })
        ->get();
} else {
    $cotas = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))
        ->where('entrada', '<=', Utils::calculaPorcentagem($porcentagem, $entrada))
        ->whereHas('saldo', function ($query) use ($parcela, $porcentagem) {
            $query->where('parcela', '<=', Utils::calculaPorcentagem($porcentagem, $parcela));
        })
        ->get();
}

return $cotas;

Is there a more elegant way to create this function? That I do not repeat the code so much, I thought to use pure SQL and go concatenating the instructions, would be a better implementation... remembering that I am beginner.

3 answers

2

You can do it this way:

$calculaPorcentagem = Utils::calculaPorcentagem($porcentagem, $credito);

$query = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', $calculaPorcentagem);

if (is_null($entrada) and is_null($parcela))
    return $query->get();

if (is_null($parcela)) 
    return $query->where('entrada', '<=', $calculaPorcentagem)->get();

$query = is_null($entrada) ? $query : $query->where('entrada', '<=', $calculaPorcentagem);

return $query->whereHas('saldo', function ($query) {
            $query->where('parcela', '<=', $calculaPorcentagem);
        })->get();

So you put it into a variable and you can reuse it in the next steps.

2


if you notice you will see that there are some lines that always repeat themselves in all conditions as:

Produto::orderBy('credito', 'DESC')
->where('id_subcategoria', $subcategoria)
->where('visivel_site', self::SIM)
->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))

Utils::calculaPorcentagem($porcentagem, $credito);

function($query) use ($parcela, porcentagem) {
    $query->where('parcela', '<=', $porcentagem);
}

Knowing this you can move them out of each if and add in conditions only one variable that summarizes the action, see;

$cotas = Produto::orderBy('credito', 'DESC')
    ->where('id_subcategoria', $subcategoria)
    ->where('visivel_site', self::SIM)
    ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito))

$porcentagem = Utils::calculaPorcentagem($porcentagem, $credito);

$parcelaQuery = function($query) use ($parcela, porcentagem) {
    $query->where('parcela', '<=', $porcentagem);
}


// você pode usar o operador ! para inverter a condição
if (!$entrada and !$parcela) {
    $cotas->where('credito', '<=', $porcentagem);
} else if (!$parcela) {
    $cotas->where('entrada', '<=', $porcentagem);
} else if (!$entrada) {
    $cotas->whereHas('saldo', $parcelaQuery);
} else {
    $cotas->where('entrada', '<=', $porcentagem)->whereHas('saldo', $parcelaQuery)
}

return $cotas->get();

0

At the time of refactoring the code and applying one of the two responses of the post I realized that I could do something a little different, using what I learned from the answers of Wictor and RFL, worth personal the answers were very enlightening:

$cotas = Produto::orderBy('credito', 'DESC')
        ->where('id_subcategoria', $subcategoria)
        ->where('visivel_site', self::SIM)
        ->where('credito', '<=', Utils::calculaPorcentagem($porcentagem, $credito));

    if (isset($entrada)) {
        $cotas = $cotas
            ->where('entrada', '<=', Utils::calculaPorcentagem($porcentagem, $entrada));
    }
    if (isset($parcela)) {
        $cotas = $cotas
            ->whereHas('saldo', function ($newquery) use ($parcela, $porcentagem) {
                $newquery->where('parcela', '<=', Utils::calculaPorcentagem($porcentagem, $parcela));
            });
    }

    return $cotas->get();

Browser other questions tagged

You are not signed in. Login or sign up in order to post.