source : blog.doubleu3.com
Oops, there’s no setTemplate() for components!
Why is this a problem? Because, without it, there’d have to be a seperate template file for each section’s action in the component. I just want to use the one template, and use the $section variable to determine what section to highlight.
The fix
The fix is to add a setTemplate() method to the sfComponents class.
It isn’t that complicated, but requires modification to a couple of files.
Add the following lines (2 methods, and one property definition) to
symfony/actions/sfComponent.class.php
/**
* Holds the sfView instance which performs the rendering.
*/
private $componentView;
/**
* @author Jared Armstrong
* Set the "View" object for this component, so that the component
* actions can modify the template for the view.
*
* @param sfView $componentView
*/
public function setComponentView($componentView) {
$this->componentView = $componentView;
}
/**
* @author Jared Armstrong
* Sets the template to use when rendering this component.
* @param string $template Name of the template to render
* (excluding _ and .php extension - automatically added since this is a component)
*/
public function setTemplate($template) {
$this->logMessage('Modifying template for component to \''.$template.'\'', 'debug');
if (isset($this->componentView) && $this->componentView instanceof sfView)
$this->componentView->setTemplate('_'.$template.'.php');
else
throw new sfException("Unable to set template for this component.
Component did not provide a sfView instance to modify.");
}
This provides the setTemplate() functionality like that of sfAction.
Now, we need to modify the code that creates the component instance and renders it, because we need to pass it the sfView instance to modify the output template which gets used.
In symfony/helpers/PartialHelper.php
function get_component($moduleName, $componentName, $vars = array()) {
...
$allVars = _call_component($moduleName, $componentName, $vars);
...
}
to
function get_component($moduleName, $componentName, $vars = array()) {
...
$allVars = _call_component($moduleName, $componentName, $vars, $view);
...
}
This passes the view instance to the method executing the component.
Now also
function _call_component($moduleName, $componentName, $vars) {
to
function _call_component($moduleName, $componentName, $vars, $componentView = null) {
and
function _call_component($moduleName, $componentName, $vars, $componentView = null) {
...
// create an instance of the action
$componentInstance = $controller->getComponent($moduleName, $componentName);
...
}
to
function _call_component($moduleName, $componentName, $vars, $componentView = null) {
...
// create an instance of the action
$componentInstance = $controller->getComponent($moduleName, $componentName);
$componentInstance->setComponentView($componentView);
...
}
Done!
Now your sfComponents should be able to successfully use the setTemplate method like that of your sfActions.
Possible better alternatives
Using the sfConfig, my guess is you can modify the class used to render ‘partials’, and when it runs the getTemplate() method, check to see if a variable has been set in the varholder that tells of a different template to use. However, the above method provides more transparency from actions to components.
Thank you Jared for this tip, wrote here to have a backup ;-)
Tags:
devloppement,
symfony,
tips