[Laravel] Relaties mergen? Voor sub-relaties

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • afraca
  • Registratie: April 2009
  • Laatst online: 13-08 16:46

afraca

Open Source!

Topicstarter
Doel: berichten die onder subcategorieen vallen ook makkelijk pagineren

https://github.com/etrepat/baum/tree/1.0.x-stable

is echt wel heel leuk. Dus we hebben categorieen, we hebben berichten. We kunnen ook andere dingen aan categorieen hangen dus wat je krijgt is ongeveer zoiets

PHP:
1
2
3
4
5
6
7
8
9
<?php

class Category extends Baum {
// for 'brevity' rest wat weggelaten
  public function berichten(){
    return $this->morphedByMany('Bericht', 'categorizable', 'categorizables');
}

}


Maar als ik
PHP:
1
Category::with('berichten')->find(15)->berichten()->paginate(10)


doe, wil ik eigenlijk berichten ook uit de subcategorieen pagineren. Hoe krijg ik dat voor elkaar? Dus je kan wel een attribute function maken "getBerichtenAttribute()" maar hoe doe je dat met de paginering dan?

edit:

Een belangrijk punt hierin is dat ik bij die pagineren rechtstreeks werk op het resultaat van berichten() , wat oplevert:
@return \Illuminate\Database\Eloquent\Relations\MorphToMany

Ik zit nu beetje hardop te denken. Er is bij de BelongsToMany class wel een orWherePivot . Als ik daar informatie over de subcategory id's ingooi, zou het eventueel kunnen, maar dat lijkt me gruwelijk lelijk.

edit2:

Wat het ook wat trickier maakt is de eager loading van berichten. Dus vanwege de Category::with('berichten') .......

edit3:
Ik wil iets proberen, maar omdat ik dynamisch methodes toevoeg aan dat model, loop ik tegen dit probleem aan: bestaat er iets als "late $this binding" in php? :/ :/

[ Voor 38% gewijzigd door afraca op 10-08-2015 12:09 ]

IMDB vote history | Next-gen OS, audio en video player, search engine en Movie DB


Acties:
  • 0 Henk 'm!

  • Douweegbertje
  • Registratie: Mei 2008
  • Laatst online: 08-09 15:03

Douweegbertje

Wat kinderachtig.. godverdomme

Leg eens uit wat je nu wilt?

Heb je een array zoals

1
..a
..b
..c
2
..a
..b
3
..a
4

En wil je dan zowel de cijfers pagineren als de letters of?

Dan zou je gewoon vooraf moeten itereren over je main items en daar ->pagination() overheen gooien, om vervolgens over je 'parent' weer de 'orignele' pagination te doen.

Als je gewoon 2 entitys hebt die je beide wilt pagineren kun je het toch gewoon allebei ophalen en mergen?

  • afraca
  • Registratie: April 2009
  • Laatst online: 13-08 16:46

afraca

Open Source!

Topicstarter

Note: De topictitel is niet echt meer helemaal waar het over gaat. Soms weet je niet welke kant je opgaat bij het schrijven van een topic....
Beetje laat nog, maar het lijkt me goed hier nog even een update over te geven. (Ik heb het ondertussen opgelost, zie hieronder)

Douweegbertje: ik denk dat jouw aanpak vanuit een iets "lager" niveau uitgaat en niet rekening houd met mijn "eis" dat ik wel graag met Eloquent ( Laravel's ORM) wil blijven werken. Het ging er een beetje om dat je relaties kan definiëren met een methode (die een 'return hasMany(..) ' doet bijvoorbeeld, en vervolgens door die methode aan te roepen je een geëxtende 'query-builder' krijgt waar al wat dingen op zijn ingesteld als het ware.

Je kan op zo'n query builder de 'paginate' optie uitvoeren. Die kijkt automatisch of er pagineringsinformatie in de url staat, berekent alle offsets en limits, en geeft je een Paginator object terug. (die implementeert een Iterable interface, en kent wat handige extra methodes om max pagina te geven enzo)

http://laravel.com/api/4....Pagination/Paginator.html

Mijn originele punt was dat ik dit wil doen:
( Ik gebruik hier 'eager loading' eigenlijk onjuist!! )

PHP:
1
2
3
<?php

Category::with('berichten')->find(7)->berichten()->paginate()


Door die eager loading kreeg ik nog extra lastigheden. En het punt is dat die 'berichten()' een query builder moet teruggeven die ook berichten selecteert die bij subcategorieën horen.

Dat bleek erg lastig. Voor die subcategorieën gebruik ik dus zo'n aparte package. Het blijft nogal een mysterie wanneer die informatie over $this->descendants() beschikbaar komt! Maar die informatie is nodig om in de berichten() de query builder al aan te passen, anders is het al te laat.

Ok, ik zal tot de conclusie komen. Ik heb het ongeveer zo opgelost:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$this->morphMethods[$resource->plural] = function ($category = null) use ($resource) {
                // For the inclusion of descendant items we allow to call with parameter set.
                // So $category->berichten($category). Only one for now
                // NOTE: we want to typehint Category, but somehow sometimes an empty array is passed...

                $base = $this->morphedByMany($resource->model_name, 'categorizable', 'categorizables');

                if (!is_null($category) && $category instanceof Category) {

                    foreach ($category->descendants()->get() as $descendant) {
                        $base = $base->orWherePivot('category_id', '=', $descendant->id);
                    }
                }

                return $base;
            };


Tadaa..... Dat is nogal lelijk :X :X De grap was dat uiteindelijk dat pagineringsobject niet persé nodig was en er dus alsnog een soort manual pagination was. Maar desalniettemin willen we wel die descendant items makkelijk erbij hebben. In gebruik ongeveer zo:

PHP:
1
2
3
4
<?php
$berichten = $category->berichten($category)->with('images')->orderBy('created_at',
                'desc')->take($per_page)->skip(Input::get('page',
                    0) * $per_page)->get()->all();


Het blijft een beetje een heikel punt, want dit is niet heel mooi vind ik zelf, zo expliciet die eigen categorie weer meegeven. Maar als ik in die functie berichten() gewoon $this->descendants() gebruik krijg ik foutmeldingen.

Mochten jullie nog betere oplossingen weten sta ik open uiteraard.

edit4: TLDR: allemaal orWherePivot('category_id', $subcategory->id) gebruikt in een loop.

[ Voor 5% gewijzigd door afraca op 13-08-2015 10:45 ]

IMDB vote history | Next-gen OS, audio en video player, search engine en Movie DB