Twig en namespaces

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

- Raoul -

- Raoul -

11/11/2012 18:17:38
Quote Anchor link
Hoi allemaal!

Een groot deel van m'n codebase is nu af, en nu is het tijd voor iets anders: templating! Heb eens gekeken naar Twig, heel mooi allemaal!
Nu zit ik toch met een probleem. Twig maakt geen gebruik van namespaces.
"Boeiend" denk je dan, maar voor m'n applicatie gebruik ik constant namespaces en om dan met Twig_X_X dingen te beginnen is een beetje raar.

Heeft twig iets als een aparte versie waar namespaces mee werken ofzo?
En als Twig dat echt niet gebruikt, is er dan een andere templating engine die met namespaces werkt?

Bedankt
Gewijzigd op 11/11/2012 18:20:53 door - Raoul -
 
PHP hulp

PHP hulp

28/11/2024 13:37:45
 
Wouter J

Wouter J

11/11/2012 18:27:18
Quote Anchor link
Nee, en er is niks raars aan. Dat is de oude manier van namespacing en helaas wordt dat nog niet door iedereen gesupport. Als je een goede autoloader gebruikt moet het geen problemen opleveren, aangezien hij wel volgens de underscore PSR-0 standaard is gebouwd.

Fabien Potencier, de maker van Twig, heeft al in 2 issues aangeven dit niet te gaan doen. Om 1 hele belangrijke reden: Het is een enorme BC break, alles zou aangepast moeten worden. Dat is bijna ondoenlijk en zal alleen gebeuren in een nieuwe major versie, maar om naar een nieuwe major versie te gaan voor alleen namespaces is het niet waard en dus is het wachten op nieuwe grote ideeën voor twig voordat we over namespaces kunnen denken.

En nog wat extra redenen:
- Twig zal niet meer werken met PHP5.2
- Twig support al de PSR-0 standaards, dat is het belangrijkste qua klassebenaming
- Klassenamen moeten opnieuw gemaakt worden, Twig_Filter_Function kan niet Twig\Filter\Function worden, hetzelfde geldt voor veel andere klassen.


Twig is de beste templating engine die je kan vinden in PHP wereld, dat zeg ik niet alleen, maar dat hoor je overal. Overstappen naar een slechtere templating engine alleen omdat hij geen namespaces support in de backend code vind ik een bar slechte rede. Je hebt maar 2 keer de niet namespace klassen nodig, voor de rest kun je alles met namespaces doen (ook twig extensies) en kun je ook in de template werken met namespaces. De enige plaats waar je even de underscore methode ziet is hier:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$loader
= new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'cache' => '/path/to/compilation_cache',
));

?>
Gewijzigd op 11/11/2012 18:29:52 door Wouter J
 
- Raoul -

- Raoul -

11/11/2012 18:30:02
Quote Anchor link
Bedankt voor je lange reactie Wouter, het lijkt me duidelijk.
Kan ik een soort van "Twig storage" class maken die mijn Storage class implements, waarmee ik die $twig variable kan returnen?
Is dat correct OO?
Gewijzigd op 11/11/2012 20:50:47 door - Raoul -
 
Kees Schepers

kees Schepers

11/11/2012 23:31:11
Quote Anchor link
WouterJ, ik vindt dat je alleen kan zeggen dat jij Twig het beste vindt, niet dat het het beste systeem is, dat mag iedereen zelf bepalen. Misschien een beetje flauw van me maar zou er wat meer objectief over reageren.

Niet dat ik overigens geen fan ben van Twig ofzo hoor, want ik gebruik het op me werk de laatste weken en ben er juist helemaal weg van omdat je embedding hebt template inheritence, macro's etc!

Raoul gebruik je een specifieke autoloader al momenteel? Bijvoorbeeld met Composer moet het geen problemen opleveren..
 
- Raoul -

- Raoul -

11/11/2012 23:41:40
Quote Anchor link
Bedankt voor je reactie Kees. Ik maak momenteel gebruik van deze autoloader: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
Dus wat bedoel je met "geen problemen opleveren"... dat ik gewoon namespaces kan gebruiken?
 
Kees Schepers

kees Schepers

11/11/2012 23:48:43
Quote Anchor link
Ja dat je gemixed namespaces en libraries die nog de oude naamgevingen hanteren Dus_Zoals_Dit als classname :)
 
- Raoul -

- Raoul -

11/11/2012 23:56:32
Quote Anchor link
Hmm, heb het nu geprobeerd maar met die van PSR werkt het niet...
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Fatal error: Class 'Twig\Autoloader' not found


Mijn bootstrap code:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php

namespace Whear\Components;

error_reporting(E_ALL ^ E_NOTICE);

require_once 'lib/Whear/Component/Autoloader.php';

\Twig\Autoloader::register(); // als testje, uitkomst => 'class not found'
?>

:s
Gewijzigd op 11/11/2012 23:57:26 door - Raoul -
 
Koen Vlaswinkel

Koen Vlaswinkel

12/11/2012 07:25:41
Quote Anchor link
Je moet wel gewoon Twig_Autoloader gebruiken i.p.v. \Twig\Autoloader, het werkt niet met namespaces.
 
Wouter J

Wouter J

12/11/2012 07:48:25
Quote Anchor link
Raoul, je moet wel de underscore PSR-0 gebruiken. Dus \Twig_Autoloader. Maar merk op dat je deze autoloader niet hoeft te gebruiken als je de PSR-0 autoloader al gebruikt, er zullen geen problemen zijn, behalve dat je misschien de path moet registreren.

Kees, daar geef ik je half gelijk in. Ik denk dat je van een aantal libraries toch wel kan zeggen dat ze 'de beste in PHP' wereld zijn, het meest gebruikt, de meeste contributors, de meeste fans. Ik vind dat bijv. een rijtje met Doctrine, Twig, het Symfony2 Form component en bijv. de Zend Mailer, ect.
Wel leuk dat je nu toch vol lof bent over Twig, dat was je vroeger namelijk totaal niet :)
 
- Raoul -

- Raoul -

12/11/2012 17:59:59
Quote Anchor link
Ok, maar mag ik dan een soort van TwigStorage maken, zodat ik niet op iedere pagina moet typen? Is dat correct OO?
 
Wouter J

Wouter J

12/11/2012 19:14:54
Quote Anchor link
Twig is geen storage, dus dat is fout. Je zou een TwigFileStorage klasse kunnen maken voor het opslaan van Twig templates.

En telkens opnieuw moet typen? In je front controller maak je 1 Twig Environment aan en die sla je ergens op, in je Registery, DIC, variabele, ect. Vervolgens moet je die telkens gebruiken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/*
 * Ergens in je bootstrap/front controller
 */

$container->set('template_parser.loader.dir', '/path/to/templates');
$container->set('template_parser.loader', function ($c) {
    return new Twig_Loader_Filesystem($c->get('template_parser.loader.dir'));
});


$container->set('template_parser.options', array(
    'cache' => '/path/to/compilation_cache',
));

// maak deze shared
$container->set('template_parser', function ($c) {
    new
Twig_Environment($c->get('template_parser.loader', $c->get('template_parser.options'));
});


/*
 * in je projecten
 */

$container->get('template_parser')->render('foo.html', array(
    'bar' => 'lorem ipsum',
));

?>
Gewijzigd op 12/11/2012 19:15:17 door Wouter J
 
- Raoul -

- Raoul -

12/11/2012 23:06:12
Quote Anchor link
Bedankt voor je reactie Wouter. Mag zo'n Registry class static zijn? Ik zie namelijk op het internet alleen maar voorbeelden van static classes.
 
Wouter J

Wouter J

12/11/2012 23:18:59
Quote Anchor link
Wat ik nu liet zien is een Service container/Dependency Injection Container (DIC). Dit is een beter pattern dan de Registry.
 
- Raoul -

- Raoul -

12/11/2012 23:23:20
Quote Anchor link
Wouter J op 12/11/2012 23:18:59:
Wat ik nu liet zien is een Service container/Dependency Injection Container (DIC). Dit is een beter pattern dan de Registry.


Hmm, dat klopt wel. Maar hoe maak ik dan die $container 'global'? Als ik op iedere pagina een $container variable maak, dan is iedere instance daarvan leeg... :s Ik kan het wel in de bootstrap doen maar dan moet ik op iedere pagina diezelfde $container gebruiken, wat nogal lelijk is. Is een Storage wel mogelijk in dit geval?
 
Wouter J

Wouter J

13/11/2012 07:56:55
Quote Anchor link
Wat bedoel je met iedere pagina? Als het goed is heb je 1 bootstrap/front controller die elke pagina request wordt aangeroepen en waar je alles in wordt geincluded.

Die container geef je gewoon mee aan een klasse, behalve als het een service klasse is (zoals Twig in dit geval), dan mag je alleen de benodigde dependencies injecteren. Voorbeeldje van het eerst:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
interface ContainerAwareInterface
{
    protected function getContainer();
    private function setContainer(Container $container);
}


abstract class ContainerAware implements ContainerAwareInterface
{
    private $container;

    protected function getContainer()
    {

        return $this->container;
    }


    private function setContainer(Container $container)
    {

        $this->container = $container;
    }
}

?>

Deze klasse kan nu elke klasse die zich bewust (aware) is van de container extenden en je hebt toegang tot de service container.
 
Kees Schepers

kees Schepers

13/11/2012 08:20:46
Quote Anchor link
Wouter J op 12/11/2012 07:48:25:
Wel leuk dat je nu toch vol lof bent over Twig, dat was je vroeger namelijk totaal niet :)


Hihi, wil nog niet zeggen dat ik het gebruik voor mijn eigen projecten ;-). Wie weet dat ik dat nog wel ga doen maar voor bijvoorbeeld mijn e-commerce platform niet, die is sowieso op Zend Framework gebouwd en performance is van best groot belang :)
 
Wouter J

Wouter J

13/11/2012 08:23:36
Quote Anchor link
Twig is behoorlijk goed voor je performance, bij je allereerste bezoeker wordt de pagina gecached in een geoptimaliseerde PHP template die vervolgens bij elke request wordt aangeroepen. In je productie omgeving moet er dus geen verschil zijn, misschien juist wel minder. In je test omgeving zal het wel wat langzamer zijn.
 
- Raoul -

- Raoul -

13/11/2012 16:53:13
Quote Anchor link
Wouter J op 13/11/2012 07:56:55:
Wat bedoel je met iedere pagina? Als het goed is heb je 1 bootstrap/front controller die elke pagina request wordt aangeroepen en waar je alles in wordt geincluded.

Die container geef je gewoon mee aan een klasse, behalve als het een service klasse is (zoals Twig in dit geval), dan mag je alleen de benodigde dependencies injecteren. Voorbeeldje van het eerst:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
interface ContainerAwareInterface
{
    protected function getContainer();
    private function setContainer(Container $container);
}


abstract class ContainerAware implements ContainerAwareInterface
{
    private $container;

    protected function getContainer()
    {

        return $this->container;
    }


    private function setContainer(Container $container)
    {

        $this->container = $container;
    }
}

?>

Deze klasse kan nu elke klasse die zich bewust (aware) is van de container extenden en je hebt toegang tot de service container.


In de bootstrap dan dit ofzo:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php

$container
= new Container;

?>


En dan op andere pagina's dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

require 'bootstrap.php';

$container->doeIets();
?>

Dat is toch lelijk?! Maar als ik dan een class extends met ContainerAware moet ik nog altijd setContainer() doen waardoor die Container instance altijd leeg is.
Gewijzigd op 13/11/2012 16:55:03 door - Raoul -
 
- Raoul -

- Raoul -

14/11/2012 18:21:26
Quote Anchor link
BUMP
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.