1

I decided to rewrite an older website that I made years ago and use templating system. I decided to use Latte, as its generating PHP files, which makes it really fast compared to systems that parse tpl every time. But I was not able to figure out, how to call a function with latte and get its result.

I am used to our custom company TPL system which can call any function and even pass parameters to it just by calling {function_name.param} or use function constants with {function::param}.

Is something like this possible purely in Latte (I am not using Nette or any other framework)? I do not want to call every single function in PHP and add it to array of parameters that TPL has to its disposal. That just makes it slower (yep I know I could use ifs in there and then ifs in TPL, but that's also an useless code duplication).

I want it to be able to call a function within class that's rendering the TPL (or its parent classes OFC) and return its output when I need it (if I even do need it), so I can avoid unnecessary calls to functions when initializing parameters for TPL parsing.

I tried to google quite a lot, but I didn't find anything useful.

I should also mention, that I am not going to use any framework at all, except Latte with Tracy and Tester for automatic testing. I do not want to use Nette or Symfony 2 etc. as the site is not that big and using whole framework would just make it even more complicated than it needs to be.

Thanks.

.

Ps.: Could somebody create tag for Latte?

pedrouan
  • 12,762
  • 3
  • 58
  • 74
MiChAeLoKGB
  • 796
  • 14
  • 38

2 Answers2

2

You can simply call any php function this way:

{? echo 'hello'}

or in newer versions of Latte:

{php echo 'hello'}

Also, you can pass instances of Nette\Utils\Html (small lib separated from framework, full of great tools even for small apps) which will be directly rendered.

Or if you want to use own class rendering output directly, simply implement __toString() function using IHtmlString interface:

class MyOwnClassRenderableByLatte implements \Latte\Runtime\IHtmlString
{
    function __toString()
    {
        return 'Hi';
    }
}

Template sample including your later questions:

{php
    // You can instantiate needed classes in one synoptical block
    // in the head of template file or reather instantiate them
    // outside of template and pass them as template variables
    $a = new ClassA();
    $b = new ClassB();
}

<div>{$a->someFunction()}</div>
<div>
    {* Or you can instantiate class inplace this way,
       but I wouldn't recommend it. BTW: This is Latte comment.
    *}
    {php (new ClassC())->otherFunction()}
</div>
Tomáš Jacík
  • 645
  • 4
  • 12
  • I LOVE YOU <3 I read their tutorials and googled a lot, yet couldn't find this simple code... `{php echo test()}` works like a charm :) I'll take a look at the Utils too :) – MiChAeLoKGB Aug 30 '16 at 10:47
  • One more question tho. How would you call a function from different class? Imagine I want to call function `test` which is in class called `Random`. I played with it and this works, but is really ugly: `{php $a = new Random; echo $a->test()}`. Is there any better way? Or will it be enough to have my main class extend Latte? I guess it would be able to access those functions then. – MiChAeLoKGB Aug 30 '16 at 12:14
  • Thanks for the edit. That was what I was thinking. Either initiated them in TPL or pass them as variables to template. But those are not really nice approaches IMO. But still, my last question: Could I just extend Latte with my classes, so Latte would be able to use class functions in TPL same way as it can use global functions? IDK how to better explain it, as I am kinda new to Latte. I always coded without anything or with our custom CRM/CMS we have at work. Thx. – MiChAeLoKGB Aug 30 '16 at 17:39
  • Don't extend Latte, better create own macros: https://latte.nette.org/en/#toc-user-defined-macros or create filter: https://latte.nette.org/en/#toc-filters – Tomáš Jacík Aug 30 '16 at 17:51
  • I was reading about macros and filters when I decided to try it, but I do not think using them for function calling is the best idea, as they would always initiate the class and call the function... I guess I got the thing about extending "latte" from forums, but it might be that they were using Constructor from Nette... What is the best way to do such thing? Right now I am trying to find out how much performance it drains to initialize classes (even if you do not use them). – MiChAeLoKGB Aug 30 '16 at 18:28
  • Extending Latte directly for adding your application functionality is against almost all design principles I know. Really, don't do that. I suppose you instantiate Latte (and all it's filters and macros with it) only once in your application. There are no performance drains to use few more macros at all. – Tomáš Jacík Aug 30 '16 at 18:31
  • Thing is, I want to use single base class, that would handle render of the latte and some other base stuff and all other classes (well, except db class etc.) would just extend that one. Then in every class itself I just want to set the template which will be used and that's it. I am too used to our system that is actually using functions from class that is rendering it without re-initializing the class. Also, I just did some tests (1.000.000 runs and used average time), and just initializing the class makes the code 3x slower, using the function from said class then slows that 2x. – MiChAeLoKGB Aug 30 '16 at 18:40
  • If I get you, you just need to show some output in latte template directly from your class. Look for my edit of original answer. If it's not what you wanted, please try to explain bit more. And tell me why you should instantiate Latte filters 1 000 000 times :) You need to instantiate them only once, when instantiating Latte itself. – Tomáš Jacík Aug 30 '16 at 18:52
  • Well, yes I want exactly that. Thing is, I want to avoid initiating a class if I do not have to do so. What I meant before is, that the average slow down just by initiating a class is 3x. I am gonna take a look at your edit... That might be what I tried to say before, but I foolishly used term `extends` instead of `implements` I just have no idea how to use it in template and how could I ever use this for multiple functions? Latte documentation kinda sucks really hard IMO. – MiChAeLoKGB Aug 30 '16 at 20:26
  • I think documentation may suck because you are trying to use Latte for something that was not designed for. I still don't get your use case and why class instantiation is problem. I really can't help you more if I don't undestand what are you trying to achieve. Try to provide some example code. – Tomáš Jacík Sep 02 '16 at 17:04
0

Try to use something like this, its same as with javascript

{some code} //is for latte expression
{ some other code} //with space after first bracket its no more latte expression

Not sure if your TPL will handle it, but you will see

If it will work, you can use more imagination and use something like

{
some fluffy code
}
Luboš Suk
  • 1,526
  • 14
  • 38
  • I guess we did not understand each other... I am not using any CMS or Framework there. I do not have my own way of calling functions. I want to be able to use Latte to call a function in PHP. I just mentioned that our CMS at work can do that and even pass parameters to functions. And I would like to know it something like that is possible with Latte. – MiChAeLoKGB Aug 26 '16 at 11:26