Wie gebruikt er datagrids en wat vinden jullie van Pike_Grid?
Sommigen van jullie zullen wel weten dat ik de laatste tijd bezig ben met een eigen open-source toolkit genaamd PiKe. Deze toolkit is een uitbreiding op Zend Framework en Doctrine2 en biedt extra functionaliteit voor de ontwikkelaar om veel gebruikte onderdelen in een applicatie snel te te bouwen.
De website vind je op Google Code
Een onderdeel hiervan is Pike_Grid. Dit is een datagrid. Pike_Grid integreerd eigenlijk Doctrine2 en jqGrid van Jquery met elkaar. Tevens is hij zeer handig te gebruiken in Zend Framework projecten.
Op alle plekken waar je tabulair data wilt weergeven waarbij functionaliteit zoals sorteren, bladeren, etc is gewenst biedt Pike_Grid met jqGrid een uitkomst. Deze doen al het werk voor je dus. Je hoeft alleen de query aan de datasource toe te voegen en eventueel wat dingen te configureren.
Onderstaand een voorbeeld van de api:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
public function indexAction()
{
//$em = Doctrine EntityManager
$q = 'SELECT u.id, u.username, u.fullname, u.emailaddress FROM My\Entity\User ORDER BY u.emailaddress ASC';
$ds = new Pike_Grid_Datasource($em->createQuery($q));
$view = $this->view;
$request = $this->getRequest();
$grid = new Pike_Grid($ds);
$grid->setCaption('Gebruikers')
->setRowsPerPage(50)
->setColumnAttribute('id', 'label', 'Nr')
->setColumnAttribute('username', 'label', 'Gebruikersnaam')
->setColumnAttribute('fullname', 'label', 'Volledige naam')
->setColumnAttribute('emailaddress', 'label', 'E-mailadres')
->addColumn('Wijzig', function($row) use($view) {
return '<a href="' . $view->url(array('action' => 'edit', 'userid' => $row['id'])) . '" title="Wijzig '.$row['username'].'">Wijzig</a>';
});
$this->view->grid = $grid;
$this->view->headScript()->appendScript($grid->getJavascript(),'text/javascript');
if($request->isPost() && $request->isXmlHttpRequest()) {
$ds->setParameters($request->getPost());
echo $ds->getJSON();
}
}
?>
public function indexAction()
{
//$em = Doctrine EntityManager
$q = 'SELECT u.id, u.username, u.fullname, u.emailaddress FROM My\Entity\User ORDER BY u.emailaddress ASC';
$ds = new Pike_Grid_Datasource($em->createQuery($q));
$view = $this->view;
$request = $this->getRequest();
$grid = new Pike_Grid($ds);
$grid->setCaption('Gebruikers')
->setRowsPerPage(50)
->setColumnAttribute('id', 'label', 'Nr')
->setColumnAttribute('username', 'label', 'Gebruikersnaam')
->setColumnAttribute('fullname', 'label', 'Volledige naam')
->setColumnAttribute('emailaddress', 'label', 'E-mailadres')
->addColumn('Wijzig', function($row) use($view) {
return '<a href="' . $view->url(array('action' => 'edit', 'userid' => $row['id'])) . '" title="Wijzig '.$row['username'].'">Wijzig</a>';
});
$this->view->grid = $grid;
$this->view->headScript()->appendScript($grid->getJavascript(),'text/javascript');
if($request->isPost() && $request->isXmlHttpRequest()) {
$ds->setParameters($request->getPost());
echo $ds->getJSON();
}
}
?>
Om even een korte uitleg te geven. De Doctrine datasource accepteerd 3 type bronnen. Een entityrepository, een DQL query of een querybuilder object.
Bij mijn query geef ik als ORDER BY u.emailaddress mee, Pike_Grid zorgt ervoor dat hierop gesorteerd wordt en ook dat als je de grid op je pagina ziet het veld emailadres gemarkeerd is als gesorteerd (met zo'n pijltje).
De view stop ik in een aparte variabele omdat use($this->view) niet mag in een closure. Je maakt het Pike_Grid object aan en geeft de datasource door.
Vervolgens kun je een hoop opties zetten. Met setColumnAttribute() kun je opties zetten die bekend zijn in de colModel van jqGrid. De rest spreekt voor zich.
Een gave feature is het toevoegen van 'dynamische' kolommen. Dus in mijn geval wou ik een wijzig kolom toevoegen voor elke rij en als data een wijzig link met daarin de gebruikerid als argument. Hier kun je dus anonmyous functies voor gebruiken. Bij het outputten van de data wordt er bij elke rij deze functie gebruikt over de betreffende toegevoegde kolom en de huidige rij als argument ($row) meegegeven zodat je diverse waarden uit die rij kan gebruiken. Misschien voor sommige complex maar het is enorm krachtig en voegt veel toe. Bovendien kun je dus view helpers gebruiken omdat $view is doorgegeven.
We voegen de grid toe aan de view waarin alleen getHTML() wordt aangeroepen of de __toString variant die hetzelfde doet. En we voegen de gegenereerde javascript toe aan de layout/view.
Omdat de grid met ajax calls werkt wordt er nog gecontrolleerd of er een POST is, zoja dan zal de datasource JSON uitspugen met gebruik van de betreffende parameters (bijv sortering, paging, etc).
Ik ben eigenlijk eens benieuwd wat jullie van Pike_Grid vinden? Het idee in iedergeval. We hebben hier al een werkende versie die snel op SVN zal staan. Ik denk dat er pas over een tijdje een echte release komt omdat er nog wel een paar dingen in missen.
En zijn er al grids die hetzelfde kunnen of nog mooier misschien?
Zal morgen proberen een voorbeeld te posten van onze applicatie :)
Gewijzigd op 17/08/2011 14:53:56 door Kees Schepers
Die API ziet er gelikt uit! Als hij dan nog werkt, is het helemaal prachtig ;).
Heb je misschien ook een gegenereerde API doc?
Waarom werken de aanpassing aan je tabel (sorteren enzo) over POST? GET is toch veel mooier/handiger/juister? Dan kan je je ook meteen leuk met routes uit gaan leven :).
En misschien leuk om eoa helper te maken voor links als deze.
Bedankt voor je reactie!
Er is nog geen API doc, dit onderdeel en eigenlijk heel PiKe is erg vers van de pers. Uiteraard gaan we nog wel api docs maken en Pieter zorgt voor de unittests.
Wat betreft je vraag over het GET/POST verhaal, dit komt eigenlijk door een beperking van jqGrid. Als we als mtype GET kiezen dan genereerd jqGrid een url als: blaat.php?sidx=c.name&nd=3 etc. Hier kan Zend Framework niet veel mee. Helaas bestaat er geen mogelijkheid (voor zover ik weet) in jqGrid om zelf de opmaak van de url aan te passen. Wel de namen van de keys.
Dus over POST leek mij voorlopig de beste oplossing..
Toevoeging op 17/08/2011 17:47:12:
Even als toevoeging een afbeelding:
http://img26.imageshack.us/img26/3110/pikegrid.png
Is een mooi voorbeeld hoe het eruit kan zien. Zoals je ziet, zie je bij naam een sorteer icoon omdat ik een ORDER BY in de query gedefineerd heb. Het wijzig icoon is dus een dynamisch kolom. Aan de functie addColumn kun je als 4e argument de search index meegeven, als je dit doet kun je deze kolom laten sorteren op een zelf gespecificeerd veld uit je query/database.
De gebruikte code in mijn UserController::indexAction:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?
/* @var $em Doctrine\ORM\EntityManager */
$em = $this->_helper->em();
$request = $this->getRequest();
$view = $this->view;
$query = $em->createQuery('SELECT u.userid, u.username, u.fullname, u.insertdate, ' .
'ug.name AS usergroup FROM BestBuy\Entity\User AS u ' .
'JOIN u.usergroup AS ug ORDER BY u.fullname DESC');
$datasource = new Pike_Grid_Datasource_Doctrine($query);
$grid = new Pike_Grid($datasource);
$grid->setCaption('Gebruikersoverzicht')
->setRowsPerPage(10)
->setColumnAttribute('userid', 'label', 'Nr')
->setColumnAttribute('username', 'label', 'Gebruikersnaam')
->setColumnAttribute('fullname', 'label', 'Naam')
->setColumnAttribute('insertdate', 'label', 'Invoerdatum')
->addColumn('edit', function($row) use ($view) {
$url = $view->url(array('action' => 'edit', 'controller' => 'user', 'userid' => $row['userid']));
return '<a href="' . $url . '"><img src="/img/admin/ico_edit.gif" alt="Wijzigen" title="Wijzig '.$row['username'].'" /></a>';
}, 'Wijzig');
$this->view->grid = $grid;
$this->view->headScript()->appendScript($grid->getJavascript(), 'text/javascript');
if ($request->isXmlHttpRequest()) {
$datasource->setParameters($request->getPost());
echo $datasource->getJSON();
}
?>
/* @var $em Doctrine\ORM\EntityManager */
$em = $this->_helper->em();
$request = $this->getRequest();
$view = $this->view;
$query = $em->createQuery('SELECT u.userid, u.username, u.fullname, u.insertdate, ' .
'ug.name AS usergroup FROM BestBuy\Entity\User AS u ' .
'JOIN u.usergroup AS ug ORDER BY u.fullname DESC');
$datasource = new Pike_Grid_Datasource_Doctrine($query);
$grid = new Pike_Grid($datasource);
$grid->setCaption('Gebruikersoverzicht')
->setRowsPerPage(10)
->setColumnAttribute('userid', 'label', 'Nr')
->setColumnAttribute('username', 'label', 'Gebruikersnaam')
->setColumnAttribute('fullname', 'label', 'Naam')
->setColumnAttribute('insertdate', 'label', 'Invoerdatum')
->addColumn('edit', function($row) use ($view) {
$url = $view->url(array('action' => 'edit', 'controller' => 'user', 'userid' => $row['userid']));
return '<a href="' . $url . '"><img src="/img/admin/ico_edit.gif" alt="Wijzigen" title="Wijzig '.$row['username'].'" /></a>';
}, 'Wijzig');
$this->view->grid = $grid;
$this->view->headScript()->appendScript($grid->getJavascript(), 'text/javascript');
if ($request->isXmlHttpRequest()) {
$datasource->setParameters($request->getPost());
echo $datasource->getJSON();
}
?>
Deze (werkende) versie staat dus momenteel alleen onder subversion op Google code. Ik wil nog eerst wat belangrijke features toevoegen voordat ik hem als download aanbiedt.
Ook zou het me leuk lijken als iemand anders een Zend_Db adapter zou willen schrijven wellicht, dan kan ik en Pieter ons volledig storten op Doctrine maar alles op zijn tijd :)
Gewijzigd op 17/08/2011 17:49:10 door kees Schepers
En, een documentatie zou echt handig zijn. Misschien is het handig deze eerst te maken, en hem daarna bij te houden (als je nieuwe functies maakt). Verder ziet het er echt gelikt uit, goed werk!
Het is een beetje dubbel en tegen de open-source regels in om Doctrine2 ook als download te gaan aanbieden, hier moet men naar de Doctrine site voor gaan.
Wat betreft de printscreen, deze template ga ik wel gebruiken maar voor mijn eigen applicatie dus. Deze heb ik ook gewoon gekocht (hete Adminus geloof ik). Niet voor Pike_Grid, die praat met jqGrid en deze weer met Jquery-UI afhankelijk van welke theme je het gedownload.
Documentatie zijn we mee bezig, ik heb al een beginnetje gemaakt zoals je kunt zien op de project pagina, maar moet inderdaad nog afgemaakt worden. Dit doe ik zijdelings langs de ontwikkeling. De documentatie van de code is wel ok!
Bedankt tot zover!
Ziet er echt leuk uit! Mijn complimenten. Ik wist dat je er mee bezig was.. Maar het (eerste) resultaat is echt leuk! Ik ga aan het eind van de week eens wat testjes uitvoeren.
Gaaf!
Niels
Ik heb even doorgekeken en een paar dingen vielen me op:
Is je Pike_Grid_Datasource_Interface niet te beperkt? Pike_Grid_Datasource_Doctrine heeft een aantal publieke methoden waar je op lijkt te vertrouwen, maar die niet in de interface staan.
Waarom gebruik je de Doctrine ORM, terwijl je nergens gebruik lijkt te maken van de object relational mapping (op het ondersteunen van een repository na). Had je niet beter (ook) met de Doctrine DBAL kunnen werken? En als je dan toch de ORM gebruikt, zou je bijvoorbeeld ook de (annotation) metadata ervan kunnen gebruiken.
Het volgende gebruik van anonieme functies heb ik nog nooit gezien:
Code (php)
Gebruik je dat vaak en is het echt handig?
Misschien leuk om een array datasource toe te voegen, zodat mensen makkelijk hun eigen kunnen maken.
Goed bezig ;-) kritiek is altijd welkom namelijk! Maar om het toch even te verdedigen haha:
De interface is inderdaad nog beperkt, dit komt omdat het design van de toolkit even wat anders was. Toen besloten om bepaalde dingen anders aan te pakken en dus even alle methods die in de interface stonden weggehaald. Omdat het nog niet helemaal af is zullen deze methods nog toegevoegd moeten worden!
Ik gebruik zeker ORM, daar zit namelijk de Abstract Syntax Tree in, die ik gebruik voor het om mappen van query metadata in treewalkers, weet niet of je zover al gekeken had? Maar dit zijn toch echt onderdelen die alleen in de ORM laag zitten van Doctrine. Ik denk dat je dus nog niet diep genoeg gekeken hebt.
Gebruik van anonieme functies is een keuze, het kan natuurlijk ook anders maar ik vond het zo wel handig. Bovendien heeft Doctrine2 een PHP 5.3 dependency dus kan ik het ook gewoon gebruiken.
Array datasource is een goede, deze zou ik van Dynagrid kunnen stelen maar de mogelijkheden zijn denk ik dan wel beperkter. Ik wil sowieso Zend_db nog (laten) toevoegen.
De AST (walkers) zijn aardig complex, ik snap er niet veel van ;).
Ik krijg wel een beetje het gevoel dat je hele ingewikkelde bewerkingen aan het doen bent om uiteindelijk vrij simpele queries te genereren, al ligt dat waarschijnlijk meer aan Doctrine.
Gewijzigd op 22/08/2011 01:05:15 door Pim -
Quote:
Ik wil sowieso Zend_db nog (laten) toevoegen.
Dat had ik aangeboden toch? :-)
Pim - op 22/08/2011 01:02:04:
Zo ver heb ik idd nog niet gekeken.
De AST (walkers) zijn aardig complex, ik snap er niet veel van ;).
Ik krijg wel een beetje het gevoel dat je hele ingewikkelde bewerkingen aan het doen bent om uiteindelijk vrij simpele queries te genereren, al ligt dat waarschijnlijk meer aan Doctrine.
De AST (walkers) zijn aardig complex, ik snap er niet veel van ;).
Ik krijg wel een beetje het gevoel dat je hele ingewikkelde bewerkingen aan het doen bent om uiteindelijk vrij simpele queries te genereren, al ligt dat waarschijnlijk meer aan Doctrine.
Ja de Abstract Syntax Tree is even pittig maar toch begin ik er wel bekend mee te worden. Op mijn werk bij het ministerie werk ik heel veel met Doctrine2 dus kan ik mijn kennis lekker bijschaven haha
Maar anders moet je mijn blogpost eens lezen over de tree en sqlwalkers, want daar zit de magic vooral in.
Maarten Buijs op 22/08/2011 07:51:11:
Mooi, ik wil hem proberen als hij helemaal af is :)
Edit: Hoe gebruik je hem.
Edit: Hoe gebruik je hem.
Hij is eigenlijk al 'af', althans al goed bruikbaar. Bij het ministerie is er al 1 applicatie in productie mee. Ik moet alleen nog uitgebreide documentatie maken. De api is eigenlijk vrij eenvoudig je moet alleen wat kennis hebben van jqGrid.
Dus als er iemand is die hem wel wilt gaan uitproberen in zijn project die kan ik eventueel wel op weg helpen op Skype ofzo.
Momenteel moet je alleen wel een SVN checkout doen om hem te gebruiken het zit nog niet in de download.
Niels Kieviet op 22/08/2011 18:24:41:
Dat had ik aangeboden toch? :-)
Quote:
Ik wil sowieso Zend_db nog (laten) toevoegen.
Dat had ik aangeboden toch? :-)
Owja das waar! Wat mij betreft kun je er al aan beginnen hoor, echt veel gaat er niet aan veranderen. Het mooie is dat alle magic vooral in jqGrid moet gebeuren!
Toevoeging
Zal ik anders voor de mensen die hem willen uitproberen voor mij een leeg Zend Framework project maken met Doctrine2 (Bisna glue) en Pike?
Gewijzigd op 02/09/2011 21:30:02 door kees Schepers
Quote:
Toevoeging
Zal ik anders voor de mensen die hem willen uitproberen voor mij een leeg Zend Framework project maken met Doctrine2 (Bisna glue) en Pike?
Zal ik anders voor de mensen die hem willen uitproberen voor mij een leeg Zend Framework project maken met Doctrine2 (Bisna glue) en Pike?
Heb je dit toevallig nog gemaakt? Ik wil het weleens uitproberen, ik heb gauw even gekeken en wat ik ervan gezien heb ziet het er goed uit.
Live example:
http://www.keesschepers.nl/pikegrid/
Je kunt de applicatie downloaden op:
http://code.google.com/p/php-pike/downloads/list
Echter die versie is ietsjes ouder je kunt beter de laatste versie uit de trunk halen met:
Code (php)
1
svn export http://php-pike.googlecode.com/svn/trunk/examples/pikegrid gewenste/naam/van/je/map
Ik ben benieuwd! Ik zal komende tijd beetje bij beetje meer voorbeelden toevoegen want de mogelijkheden zijn ongekend :)
Gewijzigd op 15/09/2011 18:23:06 door kees Schepers
Mooie blog trouwens!