Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 12.01.2017 17:08:23

next и prev для модели

Здравствуйте!
Есть задача на странице категории получать предыдущую и следующую категорию в списке отсортированном допустим по id(а вообще как угодно). При том чтобы список был зациклен, то есть для последней категории, следующей будет первая.
Написал, такой метод в модели

public static function getPrevNext($category, $attribute = 'id') {
        $cats = ServiceCategory::orderBy($attribute)->get();
        $prev = $cats->last();
        $next = '';
        foreach ($cats as $cat) {
            if($cat->getAttribute($attribute) == $category->getAttribute($attribute)) {
                continue;
            }
            if($category->getAttribute($attribute) > $cat->getAttribute($attribute)) {
                $prev = $cat;
            }
            if(!$next && $category->getAttribute($attribute) < $cat->getAttribute($attribute)) {
                $next = $cat;
            }
        }
        if(!$next) {
            $next = $cats->first();
        }
        return ['prev' => $prev, 'next' => $next];
    }

Но что-то он мне совсем не нравится. Возможно есть в ларе уже что то готовое для моей задачи?

Не в сети

#2 12.01.2017 18:15:07

Re: next и prev для модели

Готового решения нет, но можно использовать коллекции.

public static function getPrevNext($category, $attribute = 'id') {
    $current = $category->getAttribute($attribute);
    $cats = ServiceCategory::orderBy($attribute)->get();
    return [
        'prev' => $cats->where($attribute, '<', $current)->first() ?: $cats->last(),
        'next' => $cats->where($attribute, '>', $current)->first() ?: $cats->first(),
    ];
}

Изменено AlexeyMezenin (12.01.2017 19:21:02)

Не в сети

#3 12.01.2017 19:05:37

Re: next и prev для модели

  1. $cats->where($attribute, ’<’, $current)->first() ?? $cats->last()

Какой смысл здесь использовать ??, а не ?:?

Не в сети

#4 12.01.2017 19:12:45

Re: next и prev для модели

...

Изменено AlexeyMezenin (12.01.2017 19:23:03)

Не в сети

#5 12.01.2017 19:14:34

Re: next и prev для модели

Не обязательно.

PHP
$cats->where($attribute<$current)->first() ?: $cats->last()

?? отличается от ?: только тем, что не вызывает ошибок на неопределённых переменных/индексах. То есть с ?: нужно писать:

PHP
isset($array['index']) ? $array['index'] : null

А с ??:

PHP
$array['index'] ?? null

В остальных случаях разницы нет есть, см. пост constb, но насколько я помню ?? появился в PHP 7, поэтому лучше его избегать, если проект изначально не планируется для новой версии.

Не в сети

#6 12.01.2017 19:22:34

Re: next и prev для модели

Не знал, спасибо, исправил код.

Изменено AlexeyMezenin (13.01.2017 13:25:06)

Не в сети

#7 13.01.2017 12:16:42

Re: next и prev для модели

PHP?: поддерживается начиная с 5.3, PHP?? появился в 7.0

PHP?: – elvis operator, в PHP$a ?: 'xxx' мы получим PHP'xxx' если PHP$a – во-первых isset (иначе ошибка undefined) и во-вторых через PHP(bool)$a кастуется в PHPfalse

PHP?? – null coalesce operator, в PHP$a ?? 'xxx' мы получим PHP'xxx' если PHP$a – либо !isset либо === null, значения типа PHP"", PHPfalse, PHP[], PHP0 в PHP'xxx' превращены не будут(!)

Не в сети

#8 13.01.2017 15:19:52

Re: next и prev для модели

AlexeyMezenin пишет:

Готового решения нет, но можно использовать коллекции.

public static function getPrevNext($category, $attribute = 'id') {
    $current = $category->getAttribute($attribute);
    $cats = ServiceCategory::orderBy($attribute)->get();
    return [
        'prev' => $cats->where($attribute, '<', $current)->first() ?: $cats->last(),
        'next' => $cats->where($attribute, '>', $current)->first() ?: $cats->first(),
    ];
}

Спасибо за правильное направление, узнал для себя о коллекциях)) (вторую неделю в ларе ковыряюсь). Только ваш код не совсем корректен, в where нельзя указывать операции сравнения, корректный код выглядит так:

public static function getPrevNext($category, $attribute = 'id') {
        $current = $category->getAttribute($attribute);
        $cats = ServiceCategory::get();
        return [
            'prev' => $cats->filter(function ($item) use ($current, $attribute) {
                            return $current > $item->getAttribute($attribute);
                        })->sortByDesc($attribute)->first() ?: $cats->last(),
            'next' => $cats->filter(function ($item) use ($current, $attribute) {
                            return $current < $item->getAttribute($attribute);
                      })->sortBy($attribute)->first() ?: $cats->first()
        ];
    }

Не в сети

#9 13.01.2017 15:39:36

Re: next и prev для модели

Точно, where в коллекциях по-другому работает. Вообще, самый читаемый вариант - это 2 запроса в базу (3, если текущая категория первая или последняя), тогда код в пару простых строк выйдет и не придется грузить всю таблицу в память. Хотя, если таблица небольшая и код выше утравивает, то почему бы и нет.

SortBy и SortByDesc можно опустить, т.к. коллекция будет уже отсортирована при использовании orderBy() и в коллекциях помимо метода first() есть еще и метод last().

Изменено AlexeyMezenin (13.01.2017 15:42:21)

Не в сети

#10 13.01.2017 15:41:44

Re: next и prev для модели

Да это только для маленькой таблицы подходит, я это понимаю. По контексту там ни когда не будет больше 50 записей

Не в сети

Подвал раздела