I am currently implementing the navigation of the website (multilevel menu, having current page highlighted).
As navigation part will be included for virtually all modules, I first made it a global partial.
But logic for selection of "current page" is quite complicated in some situations, I am thinking of using a component for the navigation.
The problem is that symfony allows to have global partials, but not global components.
So is there a "nice symfony way" to do this?
There isn't a mechanism for this as such. I usually end up creating an empty module called default and putting stuff like that in there.
What's wrong with:
<?php include_component('someModule', 'navigationComponent') ?>
... where you store it in some general module (e.g. "general") and call it wherever you want, including your layouts. Isn't that global enough?
This is your solution:
Create the yourproject/yourapp/templates/_globalpartial.php with this content:
<?php include_component('yourmodule', 'yourcomponent'); ?>
And use this globalpartial.php in yourproject/yourapp/templates/layout.php
Related
Situation: only main page is accessible by default, all other pages needs a logged in user. When a module is loaded without user, a login template should be displayed, and no module. In other words, the $sf_content must be emptied in layout.php which is not 100% ok since there is logic in the layout. Is there elegant way for that? I dont think a helper is OK either....
Check out security filters, this is one standard way security is designed in symfony.
You even can implement your own SecurityFilter class with the functionality you want.
http://symfony.com/legacy/doc/reference/1_4/en/12-Filters#chapter_12_security
It is done by default for you by the sfBasicSecurityFilter filter. You just need a good configuration. Read this part of the Jobeet tutorial. You should use sfDoctrineGuardPlugin (or sfGuardPlugin if you using propell) for user authentication.
To complete my comments above: There are different ways to override the layout. You could use the methods:
setLayout($name)
//or using foward, which forwards current action to a new one (without browser redirection)
forward($module, $action);
inside your action class. In case you wand to modify the layout inside a filter, you can use something simular to this:
class yourFilter extends sfFilter {
public function execute($filterChain) {
if($yourConditionForOverrideTheDefaultLayout) {
//here the syntax to change the layout from the filer
$actionStack = $this->getContext()->getActionStack();
$actionStack->getFirstEntry()->getActionInstance()->setLayout('yourLayout');
}
$filterChain->execute();
}
}
To avoid unnecessary duplication in the layout file you can work with Fragments and Partials.
I've just been passed an application to work on written in smarty templates so I'm unfamiliar with how the whole thing works.
So my problem is smarty is fetching a template from a file at application level so it affects every page on the site. I need a way of telling a single template to ignore the application level fetch.
So at application level it is echo $smarty->fetch('layout/main.html.tpl'); I just want to ignore that on one template. Can anyone help?
You'd want to add some logic to whatever point in the application is fetching that template. The issue isn't smarty, it's the application. A smarty template has no way of interfering with the php that renders it, nor can it introduce logic within the php script.
You would call $smarty->fetch() from a script, not a template. You can use logic to choose a different template name and fetch whatever template is appropriate, so a single script can easily call any of your templates.
For instance...
$template = 'error.tpl';
if($conditions =='right')
{
$template = 'normal.tpl';
}
echo $smarty->fetch("layout/$template");
Also, note that you can use the display() method rather than echo with fetch():
$smarty->display("layout/$template");
This way you're not storing the template into a variable you're just going to output.
If it's a simple case where one script calls template "A" and another calls template "B"...
//call in template A
$smarty->display("layout/templateA.tpl");
//call in template B
$smarty->display("layout/templateB.tpl");
No need for extra logic in that case.
I'm creating my own script using the CodeIgniter MVC framework. Now, i want users to easily modify the site functionality and adding their own without modifying the code which i've already written.
How do i make my site pluginable ?
EDIT: The users would be the site admins. Not the end user. Basically just like drupal or joomla. Want the admin to be able to create/add plugins to extend site functionality.
There may be a better way that's specific to CodeIgniter, but this is what I would do:
First, create functions for various "hook points" in your code. Say, a function named PreArticle that you call in your code, before an article is displayed.
Allow the user to write code like this:
addHook_PreArticle('funcToCall');
function funcToCall( &$articleText ) {
$articleText = str_replace('Hello', 'World', $articleText);
}
addHook_PreArticle is a function you've defined, which would add the passed string to some internal list. Then when the PreArticle function is called, each of those functions are executed, passing in any appropriate parameters that you define.
Many CMS's Like Joomla and Blogs like Wordpress use variable function names:
$function="phpinfo";
$function();
You could load this into an array to create a list of functions that can be overridden.
That's a perfect case to use the Observer Pattern.
http://devzone.zend.com/article/5
This applies to Kohana 2.3.2
I've recently started making my Views more dynamic. Using the default template view as a base, now I am doing in the controller
$this->template->innerView = new View('article');
Then, in the middle of my template.php, I have
<?php echo $innerView; ?>
To echo the 'guts' of the article view between my header and footer. This works fine, except all the vars I defined to$this->template are inaccessible from the new view. I know I could probably do
$this->template->innerView->title = 'My Title';
But if there was a way to make child Views inherit their parent's variables, that would be great.
Is there?
The set_global() method only sets the variable to be global across all views. It's not what you think when you hear "Global" in PHP so you got it right, this is exactly what you should use when you want to make a variable available across multiple views.
http://docs.kohanaphp.com/core/view#set_global
I needed this because I use the page title in the normal template (for within <title></title>) and also as the <h2></h2> of the page.
It's as simple as this
$this->template->innerView = new View('article');
$this->template->set_global('title', 'My Title');
I'm using CodeIgniter, and will likely use their template library as I want to keep things extremely simple to use. The content for the template variables will come from the database, but I want the business admins to know what content areas are available. Basically the names of the parameters when they choose a specific template. For instance, Joomla uses an extra XML file that defines each area, whereas Wordpress uses comments within a page template to inform the system that the PHP file is a template. I like the Joomla approach because you don't have to parse the PHP file to find the areas, but I like the Wordpress approach because you don't have an extra XML file associated with every template. Are there other approaches that I'm missing?
I think the nicest way would be to add a small hack to the template parser class. The code looks quite readable and clean in system/libraries/Parser.php. You could insert a hook in that class that can be used to keep track of the variables. I don't know, if it works, but here's a snippet:
class CI_Parser {
var $varCallback;
function setVarCallback($callbackFunction) {
$this->varCallback = $callbackFunction;
}
...
function _parse_single(...) {
$callback = $this->varCallback;
$callback($key);
}
...
//Somewhere in your code
function storeVarName($variableName) {
// Persist the variable name wherever you want here
}
$this->parser->setVarCallback('storeVarName');
You could do this directly in the controller:
// in the controller
print_r($data);
$this->load->view("main", $data);
Or a little more rudimentary, but you could pass to the template a PHP array of variables (or an object):
// in the controller
$data = array();
$data["namespace"] = array(
"title" => "My website",
"posts" => array("hi", "something else")
);
$this->load->view("main", $data);
And then in the view, have a flag to print_r the namespace to show all the vars available, so that business admins know exactly what to use.
// in the view
if(isset($namespace["showAllVars"])) print_r($namespace);
One option would be to call token_get_all on the PHP file (only when your business admins are loading it up), and parse the output of that.
The best approach, in my opinion, is to keep the variable definitions in another place (such as a database table, or a separate file). This will help with testing (i.e., a programmer can't just remove a tag and it's gone) and making sure things are still working as you move on with the application development in time.
Another advantage is that your application logic will be independent from the templating engine.
On a side note, if you expect a lot of traffic, you may consider using smarty instead. We have done extensive testing with most of the templating engines around and smarty is the fastest.