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

[PHP5/Smarty] Extended class maakt variabelen leeg? *

Pagina: 1
Acties:

  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
Het probleem

Ik heb een extended class voor Smarty gemaakt die een paar dingen extra kan die ik nodig heb.
Hieronder staan de relevante stukken:

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
34
35
36
37
38
39
40
41
42
<?php

include($root . '/includes/smarty/Smarty.class.php');

class template extends Smarty {

  private $css_stack;
  private $js_stack;

  public function __construct($tpldir) {
    parent::__construct();

    $this->css_stack = array();
    $this->js_stack = array();

    $this->register_function('include_css', array(&$this, 'includeCss'));
    $this->register_function('include_js', array(&$this, 'includeJs'));
  }

  public function includeCss($params) {
    if ($params['file'] != '' /*&& !in_array($params['file'], $this->css_stack)*/) {
      $this->css_stack[] = $params['file'];
    }
  }

  public function includeJs($params) {
    if ($params['file'] != '' && !in_array($params['file'], $this->js_stack)) {
      $this->js_stack[] = $params['file'];
    }
  }

  public function display($tpl) {
    // Om te testen    
    //die('<pre>' . print_r($this->js_stack,1) . print_r($this->css_stack,1) .'</pre>');
    $this->assign('included_css', $this->css_stack);
    $this->assign('included_js', $this->js_stack);
    parent::display($tpl);
  }

}

?>


Zoals je ziet register ik in Smarty 2 custom functies die er voor zorgen dat ik in de templates css en js files kan includen zodra ik ze nodig heb, en dat die netjes in de head van mijn pagina komen te staan.

Het probleem is dat de functie wel werkt, en er ook echt dingen assigned worden, - getest door op dat punt te die(print_r)'en - maar op een of andere manier zijn de arrays js_stack en css_stack weer leeg zodra ik ze moet assignen aan de template, wat gebeurt in mijn display-functie.

Dit stukkie code wordt gebruikt in een eventplanner voor mijn vriendenkring en het grappige is dat dit letterlijk ook zo voorkomt in mijn CMS, waar het wel gewoon goed werkt.

Wat ik vermoed

Ik vermoed dat als ik in de template de functie include_js aanroep, in php vervolgens de hele zaak opnieuw geinit wordt zodat de js_stack en css_stack weer geleegd worden. Zou haast niet mogen watn mijn CMS template class werkt precies zo en doet het wel goed, maar toch. Anders moet het wel in het feit zitten dat ik in deze class parent:: gebruik.

Wat ik geprobeerd heb

Niet met de static parent:: werken, dus mijn display-functie een andere naam te geven ipv de displayfunctie van Smarty te overwriten.

heel goed gekeken wat het verschil is met de bijna letterlijk hetzelfde zijnde templateclass die in mijn CMS zit en wél werkt.

array_push geprobeerd, wat niet mocht baten. Da's natuurlijk ook gewoon hetzelfde als wat er nu staat, alleen iets mooier.

[ Voor 3% gewijzigd door _eXistenZ_ op 17-02-2008 22:25 ]

There is no replacement for displacement!


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 19-11 14:21

LauPro

Prof Mierenneuke®

Je roept nergens de constructor van Smarty aan?

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
Neu klopt maar dat gaat de andere class ook gewoon goed. Zal het toch gewoon even proberen idd :)

/edit

Code bovenaan aangepast, helpt niks.

@ hieronder, so true, aangepast.Helpt overigens nog geen zier ;)

[ Voor 38% gewijzigd door _eXistenZ_ op 17-02-2008 22:22 ]

There is no replacement for displacement!


  • Marcj
  • Registratie: November 2000
  • Laatst online: 16:32
Ik zou de parent::__construct eerst aanroepen, voordat je variabelen gaat vullen. Nu heb je namelijk kans dat de constructor de variabelen leeg maakt.

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 19-11 14:21

LauPro

Prof Mierenneuke®

Ik ben onbekend met die registerfuncties maar het nut ontgaat me eigenlijk. Je gaat eerst een functie hooken die vervolgens lekker tegen de klasse zelf aan gaat zitten schrijven, moeten die niet wat returnen?

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 20-11 13:35
Met ^^

Voor zover ik weet werkt register in smarty juist als static call die een return value verwacht. Het feit dat je er een reference naar je eigen class naar geeft helpt dan ook weinig. Documentatie lijkt dit te bevestigen:
The output (return value) of the function will be substituted in place of the function tag in the template, eg the {fetch} function. Alternatively, the function can simply perform some other task without any output, eg the {assign} function.
Sowieso is dit hele probleem merkwaardig: waarom wil je in je template (dynamisch) CSS / js files includen? Het kost je alleen maar performance, de enige reden die ik kan bedenken is dat je ermee automatisch paden etc goed zet maar dat kun je even simpel door een base url variabele te assignen.

Als je graag wilt dat al je CSS etc op dezelfde plek neergezet wordt heeft het evenmin nut aangezien register_function calls ter plekke vervangen worden door hun return value. Sowieso worden die functies pas aangeroepen zodra Smarty's parser op dat punt in je templates aankomt, dus hooguit kun je ermee een variabele (aan)vullen (door bijvoorbeeld een CSS file te appenden aan je CSS files array) om later te gebruiken, maar dan volstaat Smarty's eigen {assign} ook :)

[ Voor 7% gewijzigd door FragFrog op 17-02-2008 23:41 ]

[ Site ] [ twitch ] [ jijbuis ]


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
LauPro schreef op zondag 17 februari 2008 @ 22:45:
Ik ben onbekend met die registerfuncties maar het nut ontgaat me eigenlijk. Je gaat eerst een functie hooken die vervolgens lekker tegen de klasse zelf aan gaat zitten schrijven, moeten die niet wat returnen?
Ik heb een losse header.tpl die ik include in de meeste andere tpl's, deze is steeds het zelfde. In de header.tpl wil ik alle files listen die ik extern wil loaden, in de <head> van mijn uiteindelijke html-document. Omdat ik op sommige pagina's helemaal geen javascript nodig heb, maar op andere pagina's wel, en omdat het ding themable is en andere mensen misschien wel javascript willen op bepaalde plekken, heb ik een functie gemaakt die er voor zorgt dat de zaak wordt bewaard in een tijdelijke array die pas bij het parsen van het uiteindelijke document wordt geladen en op de goeie plek wordt neergezet, in de <head> dus.
FragFrog schreef op zondag 17 februari 2008 @ 23:38:
Voor zover ik weet werkt register in smarty juist als static call die een return value verwacht.
Dit hoeft dus niet, mijn constructie werkt perfect zoals ik verwacht in mijn CMS waar zowat dezelfde code staat.
Het feit dat je er een reference naar je eigen class naar geeft helpt dan ook weinig.
Hmm gaan we even naar kijken...
Documentatie lijkt dit te bevestigen:

[...]
Ik zie niet in wat dit er precies mee te maken heeft.
Sowieso is dit hele probleem merkwaardig: waarom wil je in je template (dynamisch) CSS / js files includen? Het kost je alleen maar performance, de enige reden die ik kan bedenken is dat je ermee automatisch paden etc goed zet maar dat kun je even simpel door een base url variabele te assignen.
Zoals ik hierboven zei ;) Het moet dynamisch vanuit elke tpl geinclude kunnen worden omdat users geen toegang hebben tot de php, en het onhandig is om voor elke pagina de hele pagina steeds weer in een tpl te stoppen ipv 1 losse header.tpl die ook nog dynamisch js en css laden kan.
Als je graag wilt dat al je CSS etc op dezelfde plek neergezet wordt heeft het evenmin nut aangezien register_function calls ter plekke vervangen worden door hun return value
Hier zit je fout, het werkt dus wel degelijk :)
Sowieso worden die functies pas aangeroepen zodra Smarty's parser op dat punt in je templates aankomt, dus hooguit kun je ermee een variabele (aan)vullen (door bijvoorbeeld een CSS file te appenden aan je CSS files array) om later te gebruiken, maar dan volstaat Smarty's eigen {assign} ook :)
Mijn functie doet veel meer dan alleen assignen, hij checkt ook offie al in de array zit, en houd een array bij ipv een losse variabele.

Om nog even duidelijk te maken wat ik doe in mijn header.tpl:

HTML:
1
2
3
4
5
6
7
8
<head>

{foreach from=$included_css item=file}<link rel="stylesheet" type="text/css" href="{$file}" />
{/foreach}
{foreach from=$included_js item=file}<script type="text/javascript" src="{$file}"></script>
{/foreach}

</head>

[ Voor 5% gewijzigd door _eXistenZ_ op 18-02-2008 00:44 ]

There is no replacement for displacement!


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Moet het wel de ene keer include_css en de andere keer included_css zijn?

{signature}


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 20-11 13:35
Voutloos schreef op maandag 18 februari 2008 @ 08:31:
Moet het wel de ene keer include_css en de andere keer included_css zijn?
include_css is de geregistreerde functie, included_css is een toegewezen array met CSS files die geladen moeten worden. Voor zover ik kan zien klopt dit wel.
_eXistenZ_ schreef op maandag 18 februari 2008 @ 00:40:
Hier zit je fout, het werkt dus wel degelijk :)
Behalve nu, bedoel je? ;)

Ik blijf erbij, zowel de manual als common sense zeggen me dat in de gecompilde template registred functies vervangen worden door static calls naar de functie in kwestie. Zou het moeten testen om het zeker te weten, maar als het zo is kan een dergelijke constructie nooit werken - ben dan ook heel benieuwd hoe je het precies in je andere systeem gedaan hebt. :)

[ Site ] [ twitch ] [ jijbuis ]


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
Ik heb deze constructie gewoon werkende in mijn CMS, is dat zo moeilijk om te geloven? Als je wil post ik daar de interresante stukken uit, die zijn hetzelfde als in de ts en werken gewoon. Het zit 'm niet in wat jij roept want het is al bewezen dat het kan door mij door het in mijn CMS ook zo te doen. Ik weet alleen niet waar het wel in zit waardoor het nu niet werkt en in mijn CMS wel.

/edit

Hmm je wou et ook zien.

Komtie: (Sorry voor de lange lap tekst)

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php

include($root . '/includes/smarty/Smarty.class.php');

class template extends Smarty {

  private $tpl_stack;
  private $css_stack;
  private $js_stack;
  public $root;

  public function __construct(){
    parent::__construct();

    global $root;
    $this->root = $root;
    $this->css_stack = array();
    $this->js_stack = array();
    
    $this->assign('root', $this->root);
    $this->assign('tpldir', $this->root . '/templates/' . $tpldir);

    $this->register_function('include_css', array(&$this, 'includeCss'));
    $this->register_function('include_js', array(&$this, 'includeJs'));
    $this->register_modifier('ss', 'stripslashes');

    $this->template_dir = $this->root . '/templates/';
    $this->compile_dir = $this->root . '/templates/templates_c/';
    $this->cache_dir = $this->root . '/includes/smarty/cache';
    $this->config_dir = $this->root . '/includes/smarty/configs';
  }

  function switchdir($dir = '.') {
    $this->template_dir = $dir . '/templates';
    $this->compile_dir = $dir . '/templates/templates_c';
  }

  function displayNotice($message, $redirect) {
    $this->assign('message', $message);
    $this->assign('redirect', $redirect);
    die($this->display('admin.notice.tpl'));
  }

  function includeCss($params) {
    if ($params['file'] != '' /*&& !in_array($params['file'], $this->css_stack)*/)
      $this->css_stack[] = $params['file'];
  }

  function includeJs($file) {
    if ($params['file'] != '' /*&& !in_array($params['file'], $this->js_stack)*/)
      $this->js_stack[] = $params['file'];
  }

  function stackTpl($tpl) {
    $this->tpl_stack[] = $this->fetch($tpl);
  }

  function displayStack($header, $footer) {
    $this->switchdir();
    $this->assign('included_css', $this->css_stack);
    $this->assign('included_js', $this->js_stack);
    $this->display($header);
    if ($this->tpl_stack != null) {
      foreach ($this->tpl_stack as $tpl) {
        echo $tpl;
      }
    }
    $this->display($footer);
  }

}

?>


Deze werkt, en hij werkt goed. Er staat in je gequote tekstje dat een functie wat kan returnen, of wat anders kan doen, zoals assign. Dan krijg je ook niks terug. Mijn functie lijkt op assign in die zin.

[ Voor 77% gewijzigd door _eXistenZ_ op 18-02-2008 10:01 ]

There is no replacement for displacement!


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 20-11 13:35
De code hierboven verschilt van je eerdere code op 1 heel belangrijk punt: je gebruikt niet display maar fetch om de templates op te halen, en je fetched voor je display gebruikt.

Effectief betekend dit het volgende:
Topicstart situatie:
1. Template wordt geladen.
2. Template wordt weergegeven.
3. Smarty komt een register functie tegen, voegt CSS dingen toe aan je CSS stack.


Bovenstaande situatie:
1. Template wordt geladen.
2. Fetch komt de register functie tegen, voegt CSS dingen toe aan je CSS stack.
3. Smarty geeft de header weer, nu staan er wel dingen in je CSS stack.
4. Template wordt weergegeven.

Kennelijk worden registred functies in tegenstelling tot waar ik vanuit ging toch uitgevoerd op het object wat je meegeeft, maar ook dan zal het alleen werken als je eerst de templates parsed (door middel van fetch) en dan pas de CSS en JS arrays assigned. Je constructie is dus wel degelijk anders, en in zijn huidige vorm zal het nog steeds nooit werken.

[ Voor 4% gewijzigd door FragFrog op 18-02-2008 10:40 ]

[ Site ] [ twitch ] [ jijbuis ]


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
Opgelost \o/

Het is zelfs nog anders, maar je hebt me behoorlijk aan het denken gezet over de volgorde waarin het gebeurde.

Ik deed in de template gewoon {include file='header.tpl'} maar dit wordt dan gedaan voordat de stacks assigned worden. Dus display ik eerst en assign ik dan pas...

Ik heb nu de custom display functie weggegooid, en de include functies zo geschreven:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
  function includeCss($params) {
    if ($params['file'] != '' && !in_array($params['file'], $this->css_stack)) {
      $this->css_stack[] = $params['file'];
      $this->assign('included_css', $this->css_stack);
    }
  }

  function includeJs($params) {
    if ($params['file'] != '' && !in_array($params['file'], $this->js_stack)) {
      $this->js_stack[] = $params['file'];
      $this->assign('included_js', $this->js_stack);
    }
  }


Ze worden assigned op het moment dat ik ze include, dan gebeurt het wel voordat ik de template display. Nu wordt er idd wel 2 keer wat assigned als je 2 files wilt includen, maar het zij zo.

/edit

Ik rewrite de include functie wel zodat de dingen op dat moment assigned worden :)

[ Voor 8% gewijzigd door _eXistenZ_ op 18-02-2008 15:42 ]

There is no replacement for displacement!


  • FragFrog
  • Registratie: September 2001
  • Laatst online: 20-11 13:35
Je weet dat je ook $this -> append kan doen he? Doet hetzelfde als een element toevoegen aan een array en die vervolgens assignen ;)

[ Site ] [ twitch ] [ jijbuis ]


  • _eXistenZ_
  • Registratie: Februari 2004
  • Laatst online: 01:07
w00t nee :D thx :D

/edit

Iig, fixed.

[ Voor 112% gewijzigd door LuNaTiC op 03-06-2009 15:42 ]

There is no replacement for displacement!

Pagina: 1