JLayout verbeteringen voor Joomla!
From Joomla! Documentation
Dit artikel laat u kennis maken met de nieuwe JLayouts
functies in Joomla! 3.2.
De meeste wijzigingen zijn gericht op het verbeteren van de flexibiliteit van het systeem voor derde-partij ontwikkelaars.
Wat geschiedenis
Laten we een voorbeeld gebruiken: u hebt artikelen die tags gebruiken, maar ook contacten, categorieën en ... hebben tags.
In het oude template systeem, voor JLayouts
(wat we nog steeds voor views wordt gebruiken) zouden we dezelfde HTML moeten kopiëren en plakken naar net zoveel plekken als dat u de de tags wilt laten zien. Dat is toch niet zo moeilijk? Ok maar als we een fout vinden dan repareert iemand dat voor content maar vergeet dat te doen voor de categorieën en dan voegt iemand een handige functie toe voor contacten, maar alleen voor contacten..... Problemen beginnen en het wordt steeds moeilijker om het systeem te onderhouden.
Yannick Gaultier heeft JLayouts
bijgedragen om dit probleem op te lossen. Een geweldig eenvoudig systeem achter het concept van herbruikbare stukjes code dat u de de mogelijkheid geeft HTML te genereren vanuit objecten/arrays met gegevens.
Voordelen van het gebruik van layouts
Dankzij het JLayout systeem kunt u de tags van een item genereren met:
echo JLayoutHelper::render('joomla.content.tags', $itemTags);
Dit toont in principe de uitvoer van het bestand in /layouts/joomla/content/tags.php
waarbij $itemTags
als parameter wordt doorgegeven voor intern gebruik. Wat we doen in modules maar op een standaard manier. Het enige vereiste is dat het $itemTags
object dezelfde structuur deelt voor alle items.
Wat zijn dus de voordelen hiervan?
Herbruikbaarheid
We hoeven maar een layout te onderhouden. Ontwerpers hoeven een layout slechts aan te passen.
Ontkoppel gegevens & ontwerp
Een ander gaaf voordeel van JLayouts
is, dat het een ander hulpmiddel is om HTML code van PHP code los te koppelen. In een ideale wereld zou 100% van de opmaak van een pagina override-baar moeten zijn door een ontwerper/ontwikkelaar zonder de Joomla! core te raken. Dit betekent dat als u een JS-bestand laadt dan zou u dat op een plaats moeten doen die een ontwerper kan overriden (overschrijven) als hij besluit uw JS niet te gebruiken maar het te vervangen door een andere library. Dit is eigenlijk een van de belangrijkste problemen die we hebben in Joomla! en de reden waarom de meeste ontwerpers angstig weglopen na een tijdje proberen samen te werken.
Makkelijke integratie in 2.5.x
Het hele layout systeem is slechts 4 bestanden. U kunt ze opnemen in uw bibliotheek voor 2.5 ondersteuning en/of integreren in uw eigen classes.
Voorgaande JLayout systeem
In het voorgaande JLayout systeem zou een aanroep als deze:
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
naar de layout zoeken in:
[0] => templates/mytemplate/html/layouts [1] => layouts
Gaaf! Dit betekent dat ik het kan overriden. Maar u zou ook de map kunnen afdwingen waar u de layouts vanaf wilt laden:
$layout = new JLayoutFile('joomla.content.tags', JPATH_SITE . '/components/com_mycomponent/layouts');
$layout->render($itemTags);
Dit zou de layouts zoeken in:
[0] => templates/mytemplate/html/layouts [1] => components/com_mycomponent/layouts
Mooi, want het is nog steeds override-baar!
Nieuwe eisen
Met het voorgaande layout systeem hebben we nog wat problemen:
- Ontwikkelaars die layouts willen gebruiken binnen hun componenten moeten het pad van de layouts bij iedere aanroep specificeren of een eigen uitgebreide classes aanmaken.
- Wat gebeurt er als een ontwerper zijn tags anders wil tonen in de blog-view als in de categorie-view?
- Hoe kan een ontwerper de manier waarop hij een veld wil genereren aanpassen voor een specifieke component?
Ik werd geconfronteerd met deze problemen in mijn werk en dat was het punt waarop ik begon het systeem te verbeteren. Sommigen hadden een "harde" oplossing bij het gebruik van het oude systeem maar ik wilde een makkelijk automatisch systeem dat ook werkt in complexe oplossingen.
Nieuwe functies
Na mijn initiële voorstel begon de Joomla! magie en kwamen mensen met meer voorstellen. Het eindresultaat een een gaaf systeem, veel beter als mijn eerste voorstel. De magie van opensource.
Als oplossing van de nieuwe verbeteringen kan dit nu de voorbeeld aanroep zijn naar de nieuwe layouts:
$layout = new JLayoutFile('joomla.content.tags', null, array('debug' => true, 'client' => 1, 'component' => 'com_tags'));
Component layout override
Een van de aanpassingen is dat het systeem nu automatisch zoekt naar layouts in het geladen component.
Nu zal dezelfde aanroep die we eerder hebben gebruikt:
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
automatisch zoeken naar layouts in deze mappen (gesorteerd op prioriteit):
[0] => templates/mytemplate/html/layouts/com_mycomponent [1] => components/com_mycomponent/layouts [2] => templates/mytemplate/html/layouts [3] => layouts
Dit betekent dat u de standaard layouts kunt gebruiken, ze kunt overriden op component niveau en de component-override kunt overriden op template niveau.
In ons voorbeeld kan een ontwikkelaar de manier waarop tags worden weergegeven in de component aanpassen en een ontwerper kan de manier waarop de tags worden weergegeven in die component overriden.
Een component dwingen
Voorgaande voorbeeld detecteert de component automatisch als de layout aangeroepen wordt. Maar wat gebeurt er als ik mijn tags wil genereren op dezelfde manier als dat zij gegenereerd worden in com_tags? Dit wordt ook gedekt door de voorbeeld-aanroep:
$layout = new JLayoutFile('joomla.content.tags', null, array('component' => 'com_tags'));
Een bron dwingen
Een ander iets dat het systeem nu automatisch detecteert is de bron waarvandaan het aangeroepen wordt. Dit betekent dat als u op de website bent het zal zoeken naar layouts op de website.
Maar als ik mijn tags in het beheergedeelte wil genereren op dezelfde manier dat com_tags ze op de website genereert! Dit wordt geregeld met deze voorbeeld aanroep:
$layout = new JLayoutFile('joomla.content.tags', null, array('client' => 0, 'component' => 'com_tags'));
De bron-parameter ondersteunt deze waarden:
- 0, 'site' > frontend
- 1, 'admin' > backend
Het toevoegen van include paths
Stel dat u eindigt met een aangepaste map voor lay-outs maar u wilt ze niet allemaal opslaan. U wilt bijvoorbeeld een map toevoegen waarvan u wilt dat Joomla naar layouts zoekt en als ze niet gevonden worden, laad dan de standaard layouts. In mijn bedrijf hebben we bijvoorbeeld een library die onze eigen gedeelde layouts bevat voor al onze componenten.
Dit wordt gedaan met de nieuwe aanroep:
$layout = new JLayoutFile('joomla.content.tags');
$layout->addIncludePaths(JPATH_LIBRARIES . '/hacknsa');
Dit voegt /libraries/hacknsa bovenaan toe om naar layouts te zoeken (maximale prioriteit). Deze methode ondersteunt ook een array met paden. Denk er aan dat in een array de laatste de hoogste prioriteit heeft.
Achtervoegsels
Een ander voorstel (in dit geval van Robert Deutz) was om het achtervoegsel van de layout te kunnen bepalen. Het originele idee was om extensies toe te staan om een lay-out voor een specifieke Joomla versie te zoeken en laden, of om de standaard versie te laden. Bijvoorbeeld:
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25')));
echo $layout->render($this->item->tags->itemTags);
Maar dat is slechts een van de mogelijkheden voor gebruik. Stel dat u een andere lay-out wilt voor RTL (van rechts naar links) talen. U kunt het toevoegen aan alle zoekresultaten om er altijd naar te zoeken in het geval dat er een RTL taal geactiveerd is. Of stel je een apart adres voor waarvan de postcode getoond wordt in verschillende formaten, afhankelijk van het land. U kunt een controle uitvoeren op een specifieke lay-out voor het betreffende land.
Sub layouts
Een van de dingen die ik slecht vond in JLayouts is dat je de instellingen van een layout niet kunt overerven en ze gebruiken om een ander klein code deel te genereren zonder alle al de opties opnieuw op te geven. Laten we een ander voorbeeld bekijken: aanpasbare facturen. Op deze manier kunt u een globale aanroep als deze doen:
echo JLayoutHelper::render('invoice', $invoiceData);
En dan binnen de layout iets als dit:
<div class="invoice">
<div class="customer">
<?php echo $this->sublayout('shopper', $displayData['shopper']); ?>
</div>
<div class="header">
<?php echo $this->sublayout('header', $displayData); ?>
</div>
<div class="products">
<?php echo $this->sublayout('products', $displayData['products']); ?>
</div>
<div class="footer">
<?php echo $this->sublayout('footer', $displayData); ?>
</div>
</div>
Wat een hoofd layout is die sub layouts aanroept. Zo kunnen gebruikers slechts de header van de factuur overschrijven zonder de rest van het systeem aan te tasten.
Bij het aanroepen van een sub layout probeert het systeem een map te vinden die een naam heeft als deze layout, met de sub layout daarbinnen. In dit voorbeeld hebben we een hoofd layout invoice.php
en binnen de map een map genaamd invoice
die de sub layout bevat (shopper.php
, header.php
, products.php
& footer.php
).
Sub layouts overerft alle instellingen doorgegeven door de bovenliggende layout. Ze zoeken in dezelfde include paden, in dezelfde client, in dezelfde component en voor dezelfde achtervoegsels.
Debug mode
Als u begint met het gebruiken van layouts met verschillende include paden, clients, componenten... dan kunt u eenvoudig eindigen met het niet weten waar het systeem de layouts vandaan haalt. Dit is waarom ik een UBU (Useful But Ugly :D, handig maar lelijk ) debug systeem opneem. Om het te activeren hoeft u alleen de optie debug
door te geven zoals:
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25'), 'debug' => true));
echo $layout->render($this->item->tags->itemTags);
U ziet iets als:
Waar geen layouts gebruiken?
Lay-outs zijn een gaaf iets indien juist gebruikt maar een verschrikkelijk iets indien gebruikt op de verkeerde plaatsen. En nu wil iedereen alles converteren naar layouts. Dit is waarom u makkelijk layouts kunt vinden gebruikt door artikelen, advertenties, contactpersonen, clients, weblinks, nieuwsfeeds. Maar u zegt misschien "maar dat is toch gaaf? We besparen op code!". Nee! We maken alleen één enkele layout met duizenden if-statements erin om om te gaan met alle verschillen tussen componenten.
Naar mijn mening zijn er geen voordelen aan het gebruik van layouts om 4 velden te generen. Dat is iets wat gedaan moet worden in het template en zal nooit hergebruikt worden buiten de core. En dit is mijn advies: als het hergebruikt kan worden buiten de core dan is het zinvol als lay-out. Voorbeelden van layouts: genereer een lijst, een knop, een menu, een veld, paginering.... Nog een goed advies: Als het niet overschreven kan worden, dan is het beter via een layout.
Layouts zijn niet de oplossing voor alles.
Ander gebruik
Stel je de huidige jQuery voor die laad in de core. Dit wordt gedaan vanuit de JHtml classes. Waarom geen JHtml zoekfunctie maken voor een automatische override van de component map? Zo kan ik mijn eigen jQuery versie hebben die getest wordt met de andere libraries in mijn component. Ja, het kan conflicteren met andere module eisen, maar hebben we dat niet allemaal? We voorkomen in ieder geval het meerdere keren laden van jQuery. Dit is niet echt een taak voor layouts maar geld ook net zo voor JHtml.
Stel je nu voor dat het bovenste menu een bug bevat bij een knop, of iets anders dat in een layout zit. U kunt dit oplossen binnen een layout override in uw eigen component en wachten tot de core het oplost. Het zelfde geldt indien u een library heeft die conflicteert met de core. Er wordt op ondersteuning bespaard met uitleg dat het een core-bug is.
Dit zijn alleen maar een paar van de ideeën achter het concept.
Conclusie
Layouts zijn een erg krachtig hulpmiddel en is een van die dingen die ons kunnen helpen de relatie te verbeteren tussen codeurs en ontwerpers. Er zijn veel plekken om layouts te gebruiken. Sommige zijn nog niet ontdekt, sommige wachten nog op iemand die het werk doet. Wilt u ons helpen?