Laravel красноречиво говорит о том, как загружать и получать отношения в отдельном массиве из коллекции коллекций. - PullRequest
2 голосов
/ 05 мая 2019

У меня проблема с получением родительских и дочерних записей в отдельном массиве.Например, у меня есть 2 модели:

1) Турнир (родитель): Турнир имеет много событий

 public function events(){

    return $this->hasMany(Event::class);
 }

2) Событие (child): события принадлежат турниру

  public function tournament(){

      return $this->belongsTo(Tournament::class);
  }

Я фильтрую события по параметрам из запроса, отправляемого контроллеру.Фильтры: 'away_team', 'home_team', 'router_id'.Я отфильтровываю события и после этого стараюсь загрузить турнир, к которому принадлежит событие, вместе с ним.

После этого я пытаюсь получить турнир и поместить их в массив отдельно.Но выкидывает память допустимую ошибку.

Я знаю, что могу увеличить память в php.ini, но я хочу принять участие в турнирах наилучшим образом - желательно с красноречивым запросом - и сократить использование памяти.У меня уже есть турниры по событиям, но проблема в том, что события находятся в коллекции, так как я могу получить как события, так и уникальные турниры в отдельной коллекции на основе запроса ввода запроса.

Вот код, который мне удаетсясделать так далекоЯ знаю, что это работает, но выдает ошибку, потому что у меня есть 10 000 или более записей:

public functions filter(Request $request){

    $query = App\Model\Event::query();

        if ($request->has('away_team')) {
            $query = $query->where('away_team.name', 'like', '%' . $request->away_team . '%');
        }

        if ($request->has('home_team')) {
            $query = $query->where('home_team.name', 'like', '%' . $request->home_team . '%');
        }

        if ($request->has('tournament_id')) {
                $query = $query->where('tournament_id', new ObjectID($request->tournament_id));
        }

        //events collection with tournament
        $events = $query->with('tournament')->get();


        //here I get Allowed memory error
        $tournaments = [];
        foreach ($events as $event) {
            $tournaments[] = $event->tournament;
        }

        $tournaments = array_unique($tournaments);

}

Итак, каково решение, чтобы получить эти записи модели в отдельные коллекции на основе следующих условий:

1) События должны совпадать с фильтрами запросов $

2) Турниры должны быть уникальными и принадлежать результату событий БД

PS: Я использую PHP-Mongo и Laravelкрасноречивый для mongo db

PS2: Я знаю, что монго не является реляционным, но вы можете использовать его как-то как

Любая помощь будет принята с благодарностью!Заранее спасибо.

1 Ответ

2 голосов
/ 05 мая 2019

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

public functions filter(Request $request)
{

    $eventQuery = App\Model\Event::query();
    $tournamentQuery = App\Model\Tournament::query();

        if ($request->has('away_team')) {
            $eventQuery = $eventQuery->where('away_team.name', 'like', '%' . $request->away_team . '%');
        }

        if ($request->has('home_team')) {
            $eventQuery = $eventQuery->where('home_team.name', 'like', '%' . $request->home_team . '%');
        }

        if ($request->has('tournament_id')) {
                $eventQuery = $eventQuery->where('tournament_id', new ObjectID($request->tournament_id));
        }

        //events collection with tournament
        $events = $eventQuery->get();

        // Get only tournaments that belongs to selected events.
        $tournaments = $tournamentQuery->whereIn('id', $events->pluck('tournament_id')->all())->get()

}

Кстати, я думаю, что если в турнирах участвуют собственные события, вы должны вызывать hasMany() в своем методе Tournament class event() и в классе Event наоборот.

Существует также возможность установить лимит на количество турниров, которые будут загружаться с каждым событием. Просто измените свой последний запрос следующим образом:

public function filter(Request $request)
{
    // ... your code

    $events = $query->with('tournament', function ($query) {
        $query->limit(10); 
    })->get();

   // ... rest of your code

}
...