> Как реализовать матричную пирамиду? Фреймворк Laravel

anonymous20

Новичок
Доброго времени суток, пытаюсь реализовать простую Матричную пирамиду. Логика алгоритма следующая, у каждого пользователя может быть только 3 подписчика, в случае если появляется 4-ый подписчик, он становится подписчиком подписчика под номером 1. Условная таблица вот такая:
То есть схема заполнения пирамиды должна быть сверху вниз - слева направо, предположим если зарегистрируются новые подписчики с id 13, 14, 15 они встанут вот сюда
Пытался сделать через циклы foreach, но непонятно как реализовать глубинное множество, их будет неограниченное кол-во
 

fixxxer

К.О.
Партнер клуба
Объясни поподробнее.

Номер корневого подписчика, от которого надо спускаться по поддереву, известен? Или просто всем по три?
Что будет, если на твоей картинке удалится пользователь номер 11? А если пользователь номер 2?
 

anonymous20

Новичок
Пользователи удалиться не могут.
На картинке просто пример, мне как-то рекурсивно нужно обходит массивы по принципу Матрицы, и на основе условия выполнять уже SQL запрос, я вот просто не знаю как по всем элементам матрицы пройтись, цикл бесконечный нужен.
 

anonymous20

Новичок
Объясни поподробнее.

Номер корневого подписчика, от которого надо спускаться по поддереву, известен? Или просто всем по три?
Что будет, если на твоей картинке удалится пользователь номер 11? А если пользователь номер 2?
Тобишь принцип такой, у пользователи может быть три подписчика, в случае если регистрируется новый, он подставляется под свободное место в пирамиде. Принцип заполнения Сверху-вниз, Слева-направо по свободным ячейкам, но каждый пользователь может иметь не более 3-х подписчиков.
 

anonymous20

Новичок
Попробовал вот так сделать, но работает только до 3-го уровня вложенности
PHP:
public function matrix($id, $follower)
    {
        if($follower->users and $follower->users->count() == 2):
            foreach($follower->users as $follower):
                if($follower->users and $follower->users->count() == 2):
                    continue;
                else:
                    $mtx = new UserFollower([
                        'user_id' => $follower->user->id,
                        'follower_id' => $id
                    ]);
                    $mtx->save();
                    break;
                endif;
                $this->matrix($id, $follower);
            endforeach;
        else:
            $mtx = new UserFollower([
                'user_id' => Auth::user()->id,
                'follower_id' => $id
            ]);
            $mtx->save();
        endif;
    }
    public function index()
    {
        return view('form');
    }
    public function store(Request $request)
    {
        $followers = UserFollower::where('user_id', Auth::user()->id)
            ->get();
        $user = new User([
            'name' => $request->name
        ]);
        $user->save();
        if($followers and $followers->count() == 2):
            foreach($followers as $follower):
                if($follower->users and $follower->users->count() == 2):
                    continue;
                else:
                    $mtx = new UserFollower([
                        'user_id' => $follower->user->id,
                        'follower_id' => $user->id
                    ]);
                    $mtx->save();
                    break;
                endif;
                $this->matrix($user->id, $follower);
            endforeach;
        else:
            $mtx = new UserFollower([
                'user_id' => Auth::user()->id,
                'follower_id' => $user->id
            ]);
            $mtx->save();
        endif;
    }
 

fixxxer

К.О.
Партнер клуба
public function matrix($id, $follower)
То есть в виде $follower явно задается корень поддерева, и к пользователю, который в это поддерево не входит, $id присоединиться не может, так?
Может ли возникнуть ситуация, когда нового пользователя присоединять не к кому (у всех уже по три подписчика)?
 

anonymous20

Новичок
То есть в виде $follower явно задается корень поддерева, и к пользователю, который в это поддерево не входит, $id присоединиться не может, так?
Может ли возникнуть ситуация, когда нового пользователя присоединять не к кому (у всех уже по три подписчика)?
Вот обновил немного логику кода
PHP:
    public function matrix($user, $follower)
    {
        $followers = UserFollower::where('user_id', $follower->user->id)
            ->get();
        if($followers->count() < 2):
            $follower = new UserFollower([
                'user_id' => $follower->user->id,
                'follower_id' => $user->id
            ]);
            $follower->save();
            return 'success';
        else:
            foreach($followers as $follower):
                if($follower->users->count() == 2):
                    continue;
                else:
                    $follower = new UserFollower([
                        'user_id' => $follower->user->id,
                        'follower_id' => $user->id
                    ]);
                    $follower->save();
                    return 'success';
                endif;
                $this->matrix($user, $follower);
            endforeach;
        endif;
    }
    public function store(Request $request)
    {
        /* Регистрируем пользователя */
        $user = New User($request->all());
        $user->save();
        /* Матрица */
        $followers = UserFollower::where('user_id', Auth::user()->id)
            ->get();
        if($followers->count() < 2):
            $follower = new UserFollower([
                'user_id' => Auth::user()->id,
                'follower_id' => $user->id
            ]);
            $follower->save();
        else:
            foreach($followers as $follower):
                if($follower->users->count() == 2):
                    continue;
                else:
                    $follower = new UserFollower([
                        'user_id' => $follower->user->id,
                        'follower_id' => $user->id
                    ]);
                    $follower->save();
                    break;
                endif;
                if($this->matrix($user, $follower) == 'success') break;
            endforeach;
        endif;
        /* Редирект */
        return Redirect::back()
            ->with('message', 'Статус выполнения: 200');
    }
Рекурсию добавил, код отрабатывает так как мне нужно, но после 3-го уровня вложенности уже не отрабатывает.(
 

anonymous20

Новичок
То есть в виде $follower явно задается корень поддерева, и к пользователю, который в это поддерево не входит, $id присоединиться не может, так?
Может ли возникнуть ситуация, когда нового пользователя присоединять не к кому (у всех уже по три подписчика)?
Такой ситуации возникнуть не может, так как пользователь свежерег всегда попадает под кого-то
 

fixxxer

К.О.
Партнер клуба
Ты не на все вопросы ответил.
Для пользователя заранее известно, в какое поддерево он попадает, или нет?
То есть, если посмотреть на твою картинку, для 13, 14 и 15 заранее известно, что они относятся к подписчику №1? Или просто попадают на первое же свободное место (скажем, 16й при ровно тех же условиях попадет к 5-му?)
 

anonymous20

Новичок
Ты не на все вопросы ответил.
Для пользователя заранее известно, в какое поддерево он попадает, или нет?
То есть, если посмотреть на твою картинку, для 13, 14 и 15 заранее известно, что они относятся к подписчику №1? Или просто попадают на первое же свободное место (скажем, 16й при ровно тех же условиях попадет к 5-му?)
Нет, заранее неизвестно в какое дерево они попадут, свободные места ищутся алгоритмом.
 

fixxxer

К.О.
Партнер клуба
Почему бы тогда просто не находить среди вообще _всех_ пользователей таких, что:
1) у них подписчиков меньше трех,
2) он сам либо является подписчиком пользователя, у которого уже заполнены все три места, либо является корневым,
3) и сортировать это все по количеству подписчиков и id пользователя,
4) limit 1, и его и берем?

Так достаточно одного sql-запроса. Если СУБД не поддерживает recursive CTE - можно ввести денормализацию, существующее количество подписчиков хранить в отдельном поле.
 
Сверху