Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[Zend] Efficiente manier om joined tables te tonen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hi mensen,

Ik werk in mijn Zend Framework netjes volgens het MVC-concept echter blijf ik steken wanneer er sprake is van joined tables.

De Zend documentatie biedt me niet de handreiking die ik graag had gevonden.

Ik heb bijv. 2 tables: Artiest, Albums.

Per table heb ik een model, mapper en een DbTable.
De mapper spreekt de DbTable aan en retourneert de gevonden data in het model. So far so good.

Maar nu wil ik een overzicht van Artiest - Albums in een tabel weergeven incl. een paginator met max X artiesten per pagina:

Artiest
- Album
- Album
- Album
Artiest
- Album
- Album
- Album

Alleen zie ik de logica nog niet hoe ik dit voor elkaar moet krijgen.
Ik maak nu gebruik van een paginator object voor de Artiest.
Vervolgens render ik deze paginator in de view maar nu komt het zeer onwenselijke... ik roep in mijn View in de foreach artiest, de bijbehorende albums op... hetgeen uiteraard totaal niet het MVC volgt.

Hoe kan ik dit slimmer aanpakken?

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

Heeft je artiest model object geen (eventueel lazy loaded) lijst van album objecten?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Topicstarter
Dat is vooralsnog geen variabele in mijn artiest model.
Die kan ik uiteraard toevoegen... echter waar ga ik deze vullen? Loop ik in de controller al door de artiest-array en ga ik dan de bijbehorende albums zoeken en toevoegen aan de artiest?
Of kan ik dat beter elders doen?

Ik zie nog niet hoe ik dit met een leftjoin kan doen hoewel ik dat wel het liefst doe i.v.m. reductie van database connecties.

'Lazy loading' zegt me niks dus daar moet ik even naar zoeken.

  • Cartman!
  • Registratie: April 2000
  • Niet online
Je kunt met de query builder gewoon joins maken, heb je dat al geprobeerd? Voor ORM is Zend_Db erg ongeschikt vind k, ik weet niet hoe ver gevorderd je al bent maar Doctrine 2 werkt veel prettiger.

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Je kunt toch gewoon dit gebruiken: http://framework.zend.com....paginator.usage.dbselect

Verwijderd

Topicstarter
@Cartman!
We doen zo ongeveer alles in Zend. Tot nog toe behoorlijk tevreden en het neemt veel werk uit handen.
Ik zal eens wat meer lezen over Doctrine maar ik vind de overstap naar een nieuwe Framework wel een grote stap.


@HuHu
Ik maak ook gebruik van die paginator echter als ik een samengestelde query gebruik zoals deze ongeveer:

"select Artists leftjoin Album on album.artiest = artiest.id"

Dan wil ik vanuit die resultaten makkelijk mijn models kunnen vullen.

Ik zal, neem ik aan, speciale mappers moeten maken voor samengestelde tabellen... of anders in mijn artiest mapper extra functies maken die de geretourneerde data splitst in artiest en album models

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Waarom die LEFT JOIN? Ik neem aan dat je een paginator maakt met iets als "select artists". Dan kun je eenvoudig pagineren over al je artiesten. En het Artist model heeft een functie getAlbums().

Verwijderd

Topicstarter
@HuHu

Uiteraard kan ik voor de Artist model een getAlbums() maken maar als ik 100 artiesten per pagina heb dan moet ik de database dus 100x benaderen. Daarom had ik gehoopt het in een gecombineerde query te doen waaruit ik vervolgens de data voor de verschillende models kan destilleren.

Ik bedenk me echter nu dat ik met een LEFT JOIN bepaalde artiesten vaker terugkrijg als joined result in geval ze meerdere albums hebben. Dan gaat mijn paginator verhaal ook niet meer op want een artiest met 100 albums zou mijn gehele pagina vullen.

Dus vermoedelijk toch naar de afzonderlijk database raadplegingen.

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Als het veelvuldig benaderen van de database een probleem is (meten = weten), dan kun je caching implementeren middels Zend_Cache.

  • Cartman!
  • Registratie: April 2000
  • Niet online
Wat jij wil is dus exact wat Doctrine voor je doet ;) Als je al heel veel gebruikt maakt van Zend_Db kan dat een behoorlijk werkje worden om te vervangen dus het is een beetje de afweging die je zelf moet maken. Ik kan je sowieso aanraden er voor een volgend project eens naar te kijken.

  • console
  • Registratie: September 2002
  • Laatst online: 20:49
Twee query's zijn genoeg;

MySQL:
1
2
SELECT * FROM `artists` LIMIT 0, 15;
^ SELECT * FROM `albums` WHERE `artist_id` IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);


Even samenvoegen in PHP en je bent klaar met twee query's i.p.v. 16.

I.i.g. zo deed ik het vroeger en tegenwoordig doen het de meeste Frameworks (?) ook die ik gebruik (Laravel bijvoorbeeld). Alleen die maken het nog makkelijker voor je, maar doen precies het zelfde als hierboven :).

  • eM.
  • Registratie: Mei 2010
  • Laatst online: 23-10 10:44

eM.

@console CakePHP doet dit ook zo. Als voorbeeld even een Album met foto's.
SQL:
1
2
3
SELECT * FROM `databasename`.`albums` AS `Album` WHERE 1 = 1 LIMIT 20
SELECT * FROM `databasename`.`photos` AS `Photo` WHERE `Photo`.`album_id` IN (1, 2, 3, 4, 5)
SELECT COUNT(*) AS `count` FROM `databasename`.`albums` AS `Album` WHERE 1 = 1


Controller

PHP:
1
2
3
4
    public function index() {
        $this->Album->recursive = 1;
        $this->set('albums', $this->paginate());
    }


Output

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(int) 0 => array(
        'Album' => array(
            'id' => '1',
            'title' => 'Fotos',
        ),
        'Photo' => array(
            (int) 0 => array(
                'id' => '1',
                'title' => 'Foto 1',
            ),
            (int) 1 => array(
                'id' => '2',
                'title' => 'foto 2',
            ),
                 )
)
Pagina: 1