Laravel - красноречивый не повторяйся - PullRequest
1 голос
/ 30 января 2020

У меня есть такой код:

$totalCount = User::sum('count_fortress');

$lastVisit = User::orderBy('last_visit_fortress', 'DESC')->first('last_visit_fortress');

$topFiveUsers = User::whereNotNull(['count_fortress', 'last_visit_fortress'])
    ->orderBy('count_fortress', 'DESC')
    ->orderBy('last_visit_fortress', 'DESC')
    ->get(['id', 'count_fortress', 'last_visit_fortress'])
    ->take(5);

return response()->json([
    "fortress" => [
        "total_count" => $totalCount,
        "last_visited" => $lastVisit->last_visit_fortress,
        "users" => $topFiveUsers
    ]
]);


$totalCount = User::sum('count_museum');

$lastVisit = User::orderBy('last_visit_museum', 'DESC')->first('last_visit_museum');

$topFiveUsers = User::whereNotNull(['count_museum', 'last_visit_museum'])
    ->orderBy('count_museum', 'DESC')
    ->orderBy('last_visit_museum', 'DESC')
    ->get(['id', 'count_museum', 'last_visit_museum'])
    ->take(5);

return response()->json([
    "museum" => [
        "total_count" => $totalCount,
        "last_visited" => $lastVisit->last_visit_museum,
        "users" => $topFiveUsers
    ]
]);

Есть ли какой-нибудь способ сделать это одним способом или что-то вроде того, чтобы поместить этот лог c в хранилище или службу вместо контроллера?

Ответы [ 2 ]

1 голос
/ 30 января 2020

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

public function scopeTopFiveUsers(Builder $query, string $context) {
    ->whereNotNull(['count_' . $context, 'last_visit_' . $context])
    ->orderBy('count_' . $context, 'DESC')
    ->orderBy('last_visit_' . $context, 'DESC')
    ->select(['id', 'count_' . $context, 'last_visit_' . $context])
}

Поскольку существует корреляция между двумя решениями, вы можете использовать некоторые умные способы использования имен столбцов и доступа к свойствам на основе на струнах с {}. Это решение на грани того, чтобы быть умным, но это решение с мышлением не повторять себя. Также используется решение области.

private function calculateResponse(string $context) {
    $topFiveUsers = User::topFiveUsers($context)->take(5);
    $lastVisit = User::orderBy('last_visit_' . $context, 'DESC')->first('last_visit_' . $context)->{'last_visit_' . $context};

    return [
        'total_count' => User::sum('count_' . $context),
        'last_visited' => $lastVisit,
        'users' => $topFiveUsers
    ]
}

public function controllerMethodOne() {
    return response()->json([
        "fortress" => [
            $this->calculateResponse('fortress');
        ]
    ]);
}

public function controllerMethodTwo() {
    return response()->json([
        "museum" => [
            $this->calculateResponse('museum');
        ]
    ]);
}
1 голос
/ 30 января 2020

Вы можете создать глобальные области видимости, как предлагалось ранее, однако, если это просто используется в качестве единственного экземпляра, то я бы, вероятно, go для чего-то вроде этого:

Route::get('user/{type?}', function ($name) {
    //point to your controller
})->where('type', 'museum|fortress');

И затем в вашем контроллер, который, конечно, назовите, что вы хотите ..

function genericSharedFunction($type){

    $totalCount = User::sum('count_'.$type);

    $lastVisit = User::orderBy('last_visit_'.$type, 'DESC')->first('last_visit_'.$type);

    $topFiveUsers = User::whereNotNull(['count_'.$type, 'last_visit_'.$type])
        ->orderBy('count_'.$type, 'DESC')
        ->orderBy('last_visit_'.$type, 'DESC')
        ->get(['id', 'count_'.$type, 'last_visit_'.$type])
        ->take(5);

    $last_visit_prop = 'last_visit_'.$type;

    return response()->json([
        "$type" => [
            "total_count" => $totalCount,
            "last_visited" => $lastVisit->$last_visit_prop,
            "users" => $topFiveUsers
        ]
    ]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...