I'm using view blocks to allow individual views to add scripts and stylesheets that are specific to those views. The resources that are used everywhere are included by default in the layout. Here's the documentation on view blocks.
Everything works as described, but the content appended in my views was getting added BEFORE the default block content (even though I was using $this->append('block name')). After a lot of aggravation, I deduced that the views were actually getting referenced first, before the layout. So the scripts I was loading in the view were getting appended to nothing. Then the layout's scripts were getting appended afterwards.
I was able to solve this problem my removing my global scripts OUTSIDE of the block. But I don't like this approach for a couple reasons. In the future, I may want my view to be able to overwrite certain things. Also, it just seems wrong and counter to what view blocks are meant for.
My questions:
1. Is the behavior I described the intended behavior?
2. Is there a better work-around to manage script dependancies from scripts appended from views?
I think blocks should not be defined in layouts, that's not the way it is intended for, it should be defined in views or elements, appended by other views or elements, and then fetched by layouts or views.
Related
I am building a page with PHP and am making heavy use of templating to split the various parts of each page up into reusable components, each of which has its own stylesheet which is automatically added to the head by script.
However, to save bandwidth and avoid style conflicts in certain situations, I would like to only link those stylesheets which are actually used on a given page. Since the head goes first in the page and the styles go in the head, but there's no way to access something like get_included_files() until the end of the page, I'd (presumably) need a way to reach back into the head and add the link tags later, but I'm not sure how to do that.
The only obvious way I can think of is to necessitate a registry array of all the components which will be used, and then use that to generate the link tags, but that is not really viable because some of the components include other components, so it would be necessary to manually register not just the components included in the top-level file, but all the components included by those components as well.
I figured out a solution. I took each of my components, and basically wrapped them in a class and a public static function of that class, called output(). I can now include() all the components I want to use right at the start, and then just do Component::output() wherever I want it to appear. This way, all the files are included, and visible to get_included_files(), by the time I call output() on the script that generates the head.
I am about to build a modular page theme in grav (which uses twig as a template engine).
By default, a modular theme consists of at least two twig template files: one provides the page frame including the head and another one that provides the markup of a content module. Grav's standard theme provides examples of these templates:
modular page frame example
module example
As you can see, the module (example) does not have a head or javascripts block to add javascripts to the html head. (This wouldn't even be possible, as a typical modular page consists of multiple modules. So if two different modules would try to change the javascripts block the last one would overwrite the changes made by the first one which would lead to unintended results).
However, it happens that I need to add some javascript code to the head of my page from within a module. I thought about a solution and had the idea to add the javascript-code as a property to an object that exists "site wide", namely the pages object.
This leads to my question:
How can I add properties to an existing object using the twig syntax?
Apart from that I would also like to know if you can think of any reasons why this solution could possibly not work. But if you help me with the syntax, I can also just give it a try...
Manipulating the state of an object shouldn't be done in a Twig template. The view should be outputting data that has been supplied to it.
try to change the javascripts block the last one would overwrite the changes made by the first one which would lead to unintended results
See this answer here for an explanation of how to have multiple blocks append content to a block rather than overwrite it. You can simply have a 'extra_scripts' block or something like that, then append any required javascript for a particular module to that block as per the described link. Essentially you need to use {{ parent() }} to ensure content is included from the parent
I'm trying to set up a Joomla-template in a way which allows me to use template parameters to choose between a number of layout variations of the template from the admin-interface. The idea is that the index.php only contains a statement which includes a php-file from a folder within the main template folder, based on the template parameters passed.
Unfortunately it seems thatmy jdoc module positions breaks whenever they are located outside the index.php file, even though it is referenced by an include-tag.
The problem is in the order that the framework builds index.php. Rather than trying to use include files, you can accomplish the same goal in a much easier and cleaner fashion. Using a combination of collapsible module positions and CSS you can manipulate the template to do basically anything you want.
You can also use template styles if you are using J1.7. A template style is basically a variation of a template that is assigned to specific menu items. Either way will work.
I am working on revamping an older CMS and I am wondering how I should handle things like multiple css and javascript files that only need to be included on certain pages.
Let's say for example I have the following pages:
services.php -> requires jquery-1.4.2.min.js
index.php -> no javascript required
However, on each of these pages, I am including a file from an includes folder
include 'includes/inc_header.php';
This file contains code like the following:
<!doctype ...>
<html>
<head>
<script type="text/javascript">...
Here is where I run into the problem. I have thought about using an array and looping through and printing each element required. This way each page could simply add the scripts they need to the array. I thought this might get very complicated very fast however.
Can anyone give me a good approach to solving this problem?
Well depending on how much work you wanna do i would reverse the view processing and move to a Front Controller that uses a 2-step view. This way your outer layout with the overall structure (doctype, head, etc.) is rendered last, allowing you to modify the output for this outer layout form within the inner layout.
While this will require potentially intensive restructuring it will give you a lot more flexibility in what you can do. Then again this probably going to be a lot of work so you would have to decide whether it is worth the investment.
You could reverse your logic on your array script idea
Inside your header output files conditionally depending on a flag
eg. (psuedocode)
array core (scripts and css for all pages)
array index (particular index scripts)
array page1 (etc)
then
if page1 merge_array core+page1
loop through and output
So your header has all the permutations but is context aware - maybe through a php variable on each page or by passing a variable to the include or reading some url parameter so only loads those required
I'm starting to understand the importance of templating in PHP. I'm using PHP itself as a template engine to avoid learning any new language. I'm still not clear on one thing tho, although I have an idea about it. I would like to know what the experts do.
Should I create a full page template, with all tables, forms and everything else (including header and footer), or should I put all of my tables, forms, etc in their own file and then add them to the template as needed.
Here's a small example to clear things up...
Should I
a) create one page with all the tables, forms, and other elements in it and use that as a final product
// Set all the information
$template->title = $username;
$template->user_info = get_user($user_id);
$template->articles = get_articles($user_id);
$template->ads = random_ad($user_info);
// Load the template with everything already in it
$template->load('user_page.tpl')
$template->display();
OR
b) create every table, form, related block element in its own file and then use those to create a final product
// set the title and load the header template
$header['title'] = $username;
$template->load('header.tpl', $header);
// get the user info as an array and load into user profile template
$user_info = get_user($user_id);
$template->load('user_profile.tpl');
// load the new article form
$template->load('new_article_form.tpl');
// get the articles as an array of info and load into user articles template
$articles = get_articles($user_id);
$template->load('user_articles.tpl', $articles);
// get a random ad based on user info
$ads = random_ad($user_info);
$template->load('advertisements.tpl');
// load the footer template and display final page
$template->load('footer.php');
$template->display();
Where every file loaded contains a small portion of what needs to be displayed on the final page.
Because of the Dont Repeat Yourself technique, I would think B, but i would like to know which and why
I would personally say the first approach is best, because it keeps all documents and document fragments semantically complete.
The second approach means that you'll have a <div> in your header.tpl that is closed by a </div> in your footer.tpl (except likely there will be a few tags that applies to). This means if you change your layout, by adding a wrapper div (for example) somewhere, you have to remember to also close it in another file (or, depending on your layout, two or three different files).
It's worse with several different embedded files. Think of how hard it is to debug a site, when one file - that gets included conditionally - has an extra </div>. You get a vague bug report "sometimes the page looks completely messed up, doesn't matter what browser I use" that is very very hard to track down. It's MUCH worse if you're using table-based layouts..
Using the first approach, you can still use the DRY principle. You load the template into a variable. eg:
$userVars['name'] = $currentUser->name;
$templateVars['userinfo'] = $template->load('userinfo.php', $userVars);
...
$template->display('template.tpl', $templateVars);
You can continually nest documents that way. There are many benefits:
Each file is semantically complete HTML - all tags that are opened, are also closed in the same document. It's easy to edit one part of the layout without breaking (possibly unknowningly) anything else.
It's each to cache the output of certain templates, and re-use them
It's easy to apply AJAX to the site. For example, you have a stats.tpl template rendering inside a <div id="stats"> on the first page load. You also have a view that just renders the stats.tpl template by itself, and then use jquery to do $('#stats').load('/ajaxstats.php'), which refreshes that div but without repeating code at all.
Template inheritance for structures common to every template (e.g. layout; header/footer), and template embedding (i.e. including) for reusable bits (e.g. forms).
With approach A and without inheritance, you'd be either including common layout elements (which is IMHO ugly), or duplicating entire layout in every template (which is even worse). And plain approach B would create massive amounts of tiny template bits for everything, which may reduce maintainability.
And for that, I really recommend using real, dedicated templating engine instead of plain PHP. They make life easier (inheritance is one thing; another - variable auto-escaping).
template inheritance would probably make the cleanest code. you can do this now in straight php using PHP Template Inheritance
There is no good or bad solution. There are techniques and guidelines but in time you will learn what approach is better than others.
Just by looking at it i would say that the second approach allows you to be more flexible and breaks down the page into smaller parts. Smaller might some times mean more manageable.
Also the second solution also allows more than 1 persons working on the page since they will only need to work/change parts of the page and not the whole page.
regards,
As gregmac suggested, the first solution is probably preferable. Having said that, I would also suggest to have a look at the various PHP frameworks available, most of which implement templates using various techniques.
Have a look at this list for a start. You may also want to take a look at some stand-alone template engines, such as Smarty, in order to get some ideas or to avoid implementing your own engine.