How to fetch() sub-parts of a Smarty template - smarty

Background Smarty is a templating engine that separates the presentation layer from the logic layer of web applications. It is well-suited for the Model-View-Control approach to developing web applications. The View can be represented by Smarty templates, which contain only HTML and Smarty tags. The Control can be implemented by PHP files that serve the appropriate views based on the logic contained within them via PHP code. The View is instantiated by displaying the templates via the display() command. Alternatively, a template can be read in as a variable without displaying it via the fetch() command. The file name of the template is the argument to both these commands.
Issue The fetch() command can read an entire template. In order to read parts/sub-parts of a template, each of these parts would normally needed to be stored in a separate file with its own name that can be the argument to the command. This creates needless files.
Question Is it possible to fetch only parts of a Smarty template by somehow marking sections of the template?
Case example Below I present a sample template file with Smarty and HTML tags, as well as the corresponding controller file with PHP code.
Template file (index.tpl)
<html>
<body>
<div id="sec1">
First section
</div>
<div id="sec2">
Second section
</div>
</body>
</html>
Controller file (index.php)
<?php
$smarty = new Smarty;
$template = $smarty->fetch("index.tpl");
?>
In the example above, the $template variable would contain the full output from the template page. Below is a dump of its contents from the example.
$template => string(255)
"<html><body>
<div id="sec1">First section</div>
<div id="sec2">Second section</div>
</body></html>"
However, suppose I wish to read in the code from each of the DIV containers separately, and store them into separate variables, how could I achieve this? For instance, suppose I have a magical function called fetch_sub(). Here's my expectations of using it.
<?php
$smarty = new Smarty;
$div1 = $smarty->fetch_sub("index.tpl", "sec1");
$div2 = $smarty->fetch_sub("index.tpl", "sec2");
?>
Then $div1, etc would contain only the relevant sub-part, instead of the whole template.
Other info I am not a beginner with Smarty and have a fairly good handle on basic concepts, as well as some of Smarty's advanced concepts. Following is my attempts so far at conceptualizing the problem and getting to a solution. My initial rough idea is to demarcate the template into sections using {capture}, and then somehow reference each of these sections. I present an outline example of the idea below.
{capture name=sec1}
<div id="sec1">
First section
</div>
{/capture}
. . .

Smarty (as of Smarty 3.1) has no built-in feature to allow you achieving your goal. I had proposed something similar in 2011, but we haven't come around to implementing it.
Maybe you can have the generated HTML parsed to DOM and help yourself with xpath, or something like that?

You can try this:
sec1.tpl
<div id="sec1">First section</div>
sec2.tpl
<div id="sec2">Second section</div>
index.tpl
<html><body>
{include file="sec1.tpl"}
{include file="sec2.tpl"}
</body></html>
And then You can fetch parts by invoking:
$smarty = new Smarty;
$div1 = $smarty->fetch("sec1.tpl");
$div2 = $smarty->fetch("sec2.tpl");

Related

Laravel #yield showing content with HTML tags

I'm new to Laravel and I faced this issue, when I'm using #yield('content') to view some HTML, the out put will be the exact contact with decoding it into HTML.
Here is my code :
#yield('content',"<p>This is a great starting point for new custom pages</p>")
And the out put is : <p>This is a great starting point for new custom pages</p>
And here is a screenshot :
Can someone help me know what's going on please?
In Laravel, the #yield directive is looking to pull the #section that you note up from whichever file is producing the html. When you pull in the #section, it is formatted as proper html on the page.
So, if you had a section like this:
#section('paragraph')
<p>here is some text</p>
#stop
And pulled this in a #yield statement:
#yield('paragraph')
This would simply output the html:
here is some text
What you have done with this:
#yield('content',"<p>This is a great starting point for new custom pages</p>")
is to supply default text to display on the screen if the 'content' section is unavailable. This text is escaped, thus you are seeing the html tags.
#Mousa Alfhaily, You do not have to pass the return value with the html tags
If you want to paragraph the return value... Then you do that at where the content is been rendered
#yield('content',"<p>This is a great starting point for new custom pages</p>")
it should be
#yield('content')
then your
#section('content')
$var = "This is a great starting point for new custom pages";
<p>
{{$var}}
</p>
#endsection
The #section directive, defines a section of content, while the #yield directive is used to display the contents of a given section.
So, if you had #section like- #section('paragraph')...#endsection.
then, #yield must be like - #yield('paragraph')
Example
In #yielddirectives -
#yield('content')
In #section directives-
#section('content')
...
your html content
...
#endsection

What's the difference between Laravel Blade's `#yield` and `#include`?

I'm learning Laravel (starting at version 5.3) and these two Blade directives look very similar, the only difference I know is that #include injects the parent's variables and can also send other variables.
What's the difference between #yield and #include?
When should I use #yield?
When should I use #include?
#yield is mainly used to define a section in a layout. When that layout is extended with #extends, you can define what goes in that section with the #section directive in your views.
The layout usually contains your HTML, <head>, <body>, <header> and <footer>s. You define an area (#yield) within the layout that your pages which are extending the template will put their content into.
In your master template you define the area. For example:
<body>
#yield('content')
</body>
Let's say your home page extends that layout
#extends('layouts.app')
#section('content')
// home page content here
#endsection
Any HTML you define in the content section on your homepage view in the 'content' section will be injected into the layout it extended in that spot.
#include is used for reusable HTML just like a standard PHP include. It does not have that parent/child relationship like #yield and #section.
I highly suggest reading the Laravel Blade documentation for a more comprehensive description.
#include and #yield are two completely different types of operations to import code into the current file.
#include - import the contents of a separate file into the current file at the location in which it is placed. i.e.:
Layout file:
< some html or other script >
#include('include.file_name') // "include." indicates the subdirectory that the file is in
< more html or other script >
Include File ( a blade file with a block of code ):
< some cool code here >
The contents of 'file_name' ( also a blade file ) is then imported in where the #include directive is located.
#yield imports code from a "section" in the child file ( the "view" blade file. ) i.e.:
Layout file:
< some html or other script >
#yield('needed_section_name')
< more html or other script >
The following section is needed in the "view" blade file that is set to "extend" that layout file.
"View" blade file:
#extends('layout.file_name')
... code as neeeded
#section('needed_section_name')
< some cool code here >
#stop
...
more code as needed
Now the layout file will import in the section of code that matches the naming used.
More on the subject here....
The difference between #yield and #include is how you use them.
If you have a static kind of content, like a navbar, this part of the page will always be in the same place in the layout. When you use #include in the layout file, the navbar will be put once per layout. But if you use #yield you will be enforced to make a #section of the navbar on every page that #extends the layout.
#yield is, on the other hand, a better choice when content is changing on all the pages but you still want to use the same layout everywhere. If you use #include you'll have to make a new layout for every page, because of the difference of content.
Today I was trying to figure out this difference as well, and where to use each, and why would I want to use one over the other. Please be warned this answer is verbose and probably very over-explained.
Snapey from the Laracasts forums got me started thinking about them properly:
https://laracasts.com/discuss/channels/laravel/whats-the-difference-between-atinclude-and-atyield
First off, #include is going to include an entire file, just like the PHP include function. That's great if you're just dumping an entire file of content into the <body> of your page, for example the following is going to include everything inside of 'content.blade.php':
<!-- layout.blade.php -->
<body>
#include('content')
</body>
<!-- content.blade.php -->
<div>
<div>
<p>Hey this is my content.</p>
</div>
<div>
<span>and stuff</span>
</div>
</div>
But #yield, in conjunction with #extends and the #section and #endsection directives, will allow you to have your content chunked into separate sections, but kept all in one file. Then you can #yield it into the layout in separate chunks. The visual that comes to mind is shuffling one half of a deck of cards into the other half, in a classic "riffle" shuffle:
<!-- content.blade.php -->
#extends('layout')
#section('top_content')
<h1>Hey I'm the title</h1>
#endsection
#section('middle_content')
<p>Hey how's it going</p>
#endsection
#section('other_content')
<p>It's over now.</p>
#endsection
<!-- layout.blade.php -->
<body>
<div>
#yield('top_content')
</div>
<p>Some static content</p>
<div>
#yield('middle_content')
</div>
<p>Some more static content</p>
<div>
#yield('other_content')
</div>
<div>Static footer content of some kind</div>
</body>
Secondly and maybe more importantly, the flow of control is sort of inverted, in a way that makes everything much more coherent. In the first example, with #include, you'd be calling the layout file with the view helper, in sort of a top-down way. For example this might be your code:
Route::get('/', function () {
return view('layout');
});
But with #yield and #extends, (as in the second example) you call the content file itself, and the content file will first look at the #extends directive to drape itself with the layout file, like it is putting on a coat. So it happens in reverse, in a sense, like bottom-up. Then the #yield directives inject the content as specified. The content file is who you are talking to in your router/controller:
Route::get('/', function () {
return view('content');
});
You call the content view, it looks at the #extends directive to pick the layout, and then the #yield directives in the layout file inject the matching #section sections into the layout.
So this way is much more useful because in practice you'll be referring to different content when you refer to different views.
If you were only using the #include statement to build your views, then you'd have to pass a different content slug to the layout file that you are calling every time, maybe like this:
Route::get('/welcome', function () {
return view('layout', ['content' => 'welcome']);
});
Route::get('/profile', function () {
return view('layout', ['content' => 'profile']);
});
<!-- layout.blade.php -->
<body>
#include($content)
</body>
And that seems like a mess to me.
That all being said, #include seems like a great way to include a little snippet in your layout file (the one called by the #extends directive), like the nav bar, or the footer, or something you just want to separate out of your layout file for organizational purposes.
#yield should be used when your contents will be changed
#include should be used for contents that wont change. e.g header, footer
#include used for reusable code like navbar, we have to design navbar one time and use it in our whole site.
#yield used for sections that change again and again like body.
for example you have already your layout structure where you #include('some scripts or style'). it will not allow you to change its directive while #yield you can change its content. means you create a section to yield into your layout.blade.php. you can use yield also if you have a specific script or style in each page.
#include('layouts.nav') //default when you call layout.blade.php
<div class="container">
#yield('content') //changes according to your view
</div>
#include('layouts.footer') //yes you can use #yield if you have specific script.

Using Laravel Blades

i have started working in Laravel, and working with .blade.php templates, but am not able to understand the benefit for using blad.php and also while having a master page, why we put our code in some other pages with #sections and #yeild
like
masterpage.blade.php
<div>
#yeild(section)
</div>
index.balde.php
#section
Hellow world
#endsection
why i need to do it like that? why we can't just put our Text in the same page instead of doing this method, what are the benefits if we code like that.
There are lot of benefits in using Blade with Laravel, please read it here
http://culttt.com/2013/09/02/using-blade-laravel-4/
The short answer for you questions is we do not need Blade engine in any project. However, using it brings many benefits.
Simplify script file
Like other templating engine, Blade engine simplify your PHP scripts by some replacement such as :
<?php echo $foo ?> changed to {{ $foo }} (reduce 8 characters)
<?php if ($condition): ?> changed to #if ($condition) (reduce 6 characters)
<?php echo trans('lang.key') ?> changed to #lang('lang.key') (reduce 11 characters)
...
Try to calculate how many character you can save if using Blade engine in your script.
Another thing I love in Blade engine is that we can create our own custom control structure. If you are tired of typing $var->format('Y-m-d H:i:s') every time you need to output a DateTime object. You can create custom matcher with Blade
Blade::extend(function($view, $compiler)
{
$pattern = $compiler->createMatcher('datetime');
return preg_replace($pattern, '$1<?php echo $2->format('m/d/Y H:i'); ?>', $view);
});
Now, all you need to to is replace $var->format('Y-m-d H:i:s') by #datetime($var).
View inheritant
By supporting section, Blade engine help developer organize their view file in a hierarchical and logical way. Imagine that you have HTML code for some pages of your website: a home page, a category archive page and a single post page. All there page have the same header, footer and sidebar. If we " put our Text in the same page instead of doing this method", the content of there files have a large amount of similarities, which cause any changes in the future very painful.
With Blade sections, create a simple master layout file like that
<html>
<body>
#section('sidebar')
<!-- this is header code -->
#show
#section('sidebar')
<!-- this is sidebar code -->
#show
<div class="container">
#yield('content')
</div>
#section('footer')
<!-- this is footer code -->
#show
</body>
</html>
In the view file for each page, you only need to take care of the main content of the page, instead of other parts.

CodeIgniter - Smarty - How to fetch templates into a master template from one place in CodeIgniter

It's a little bit hard to explain what's my question about but I going to try :)
In custom projects where I'm using Smarty, I have an index.php file where all the basic settings for url handling and stuff is placed.
For example:
// Get information for the "about us" page
if($_GET['qs']=='about_us'){
$data['text'] = 'Lorem Ipsum...';
$data['other_stuff'] = 'dolor sit amet';
// Required template file
$data['tpl_Name'] = 'about.tpl';
}
At the bottom of this file I have a bit of code that fetches the correct template end sends it to a master_site template.
For example:
if (isset($data['tpl_Name'])){
$this->smarty->assign('content', $this->smarty->fetch($data['tpl_Name']));
$this->smarty->view('master_site.tpl');
}
In the master_site.tpl I can access the about.tpl by using {$content}
This {$content} variable will change for every page because the index.php is the page where all the data will be send to by requesting a page in my application.
Question: Is there a file in CodeIgniter thats available on every page so I can create something like above? Right now I have to use this piece of code (second example) in every function of my controller and that seems inefficient.
Of course i have to set $data['tpl_Name'] in every function but thats no problem.
Thanks.
There are a handful of ways to integrate a template library into CodeIgniter, and a lot of it depends on how you want to tie your templates together. The following may suit you well, or maybe just point you in the right direction. It's not the only Smarty/CI solution to templates, but it's the one I'm familiar with.
I wrote some code to integrate Smarty into CI. It allows you to use the standard way of loading views -- $this->load->view('view', $data) -- but you get to use Smarty's syntax within the files.
The way I handled a "master" template is through Smarty's {extends} (template inheritance docs). The individual views that I load all extend either a main template, or some other hierarchy that leads to one.
main_template.php:
<html>
<head>
<meta>
<meta>
<title>{$title|default:"Default Title"}</title>
</head>
<body>
<header>
<h1>My Website</h1>
</header>
<nav>
<ul>
<li>Page Link</li>
<li>Page Link</li>
<li>Page Link</li>
<li>Page Link</li>
</ul>
</nav>
<section class="main-content">
{block name=content}{/block}
</section>
<footer>
© 2013 Me!
</footer>
</body>
</html>
page.php:
{extends "main_template.php"}
{block "content"}
<h2>My Content Page</h2>
<p>Lorem ipsum and stuff...</p>
{/block}
The $title variable would be added to your view data like normal, and you'd load the page with the standard syntax:
$data['title'] = 'My page';
$this->load->view('page', $data);
I'll let you investigate the Smarty docs to get more in-depth details, but that's what I've done before. :)

How do I separate the files for 'widgets' in codeigniter?

I have a basic cms that loads content into pages that have mustache tags to indicate where in the html code those contents will appear.
The contents are specified in a widget model which indicate which type of content is to be displayed, so for example, freetext with id. or another model and id. each one of those models will be displayed differently based on the model they are based on.
I can imagine this becoming and bit unwieldy, is there a way to have a separate folder to put those widgets in so that it doesn't clutter my main code.
Something like apotomo does on rails would be good, but for codeigniter.
A widget model? That is not so nice. Have you tried looking at PyroCMS?
https://github.com/pyrocms/pyrocms/blob/master/system/pyrocms/modules/widgets/libraries/Widgets.php
From the sound of it you may be more interested in our Plugins library (sounds like the same thing with a different name). It is set up with a MY_Parser and runs on top of Dan Horrigan's Simpletags implementation.
Either way this has all be done plenty. If you want some more specific tailored advice you might have to demo some of your code.
Create a folder inside application/views called widgets. Put your widgets inside that folder and create a separate file for each widget (d0h).
Next, you have 2 options (at least that i know of):
a.) Load the widgets into variables inside the controller, then pass them to the main/general view
$data['widget_twitter_feed'] = $this->load->view('widgets/twitter', '', false);
$data['widget_something'] = $this->load->view('widgets/something', '', false);
$this->load->view('my_main_view', $data);
b.) Load the widgets inside the main/general view itself
<html>
...
<div id="sidebar">
<?php $this->load->view('widgets/twitter'); ?>
</div>
...
<div id="footer">
<?php $this->load->view('widgets/something'); ?>
</div>
...
</html>

Resources