Rob Wilkerson
Rob Wilkerson

Reputation: 41256

Symfony: Sharing a partial between two component actions

I have a component that has been happily building and rendering menus for a while now. Now I have to provide for a special case that shares all of the same logic, but requires a little bit of work in front of what already exists. What I'd like to do is create a new component action that will do the necessary preprocessing, punt to shared logic to complete the computational side and then render through the existing template partial (when all is said and done, it's still a menu like any other--it just take a little more work to build it).

Unfortunately, I can't find any way of doing this.

Here's the high level file/code breakdown that I have right now:

# 
# navigation/actions/components.class.php
# 
public function executeMenu() {
  /** 
   * This method runs most of the menus and does most of the work 
   * that's required of the special case.
   * 
   * Once complete, of course, it renders through navigation/templates/_menu.php
   */
}

public function executeSpecialMenu() {
  /** 
   * Do some preparatory work and delegate to executeMenu()
   * to finish up and render the menu. I'd like this action 
   * to render through the _menu.php partial as well.
   */
}

# 
# templates/layout.php
# 
<?php include_component( 'navigation', 'menu', array( 'menu' => 'Entity Type' ) ) ?>

/** SNIP */

<?php include_component( 'navigation', 'SpecialMenu' ) ?>

Any input would be much appreciated.

Upvotes: 2

Views: 2761

Answers (5)

Ashton Honnecke
Ashton Honnecke

Reputation: 717

A more elegant solution is to use the get_partial inside the "second" component's execute function, like so:

public function executeSpecialMenu() {
    //forces SpecialMenu to render _menu.php
    echo get_partial('menu', $this->varHolder->getAll());

    return sfView::NONE;
}

The call to varHolder->getAll gets all the variables that were going to be passed to the "normal" partial, since get_partial requires that.

Or, as a new method:

public function executeSpecialMenu() {
    return $this->renderAlternatePartial('menu');
}

protected function renderAlternatePartial($partial) {
    echo get_partial($partial, $this->varHolder->getAll());
    return sfView::NONE;
}

Upvotes: 2

Dziamid
Dziamid

Reputation: 11609

I wouldn't recommend to use different actions to render the same entity. Try to combine them and call a component with different parameters, and if it is heavy, move all the logic to a separate class.

Upvotes: 0

Alireza Kazemi
Alireza Kazemi

Reputation: 130

Also there exists a renderPartial('xxx') method in the action class which is useful when it is needed to generate a part without template in cases such as XmlHttpRequest s:

if ($request->isXmlHttpRequest())
{
  return $this->renderPartial('module/action', array('param' => 'value'));
}

I haven't tested if this works in the component execute methods. If this does not work it is a good idea to add such a functionality to symfony sfComponent class.

Upvotes: 1

Alireza Kazemi
Alireza Kazemi

Reputation: 130

In the action/template mode, there exists a $this->setTemplate('xxx') method (in the action class) which can use a same template for different actions. (e.g same template for new or edit actions). Would that there was such a method in the component classes.

Upvotes: 0

Raise
Raise

Reputation: 2034

A simple if non-optimal way would be to create the _SpecialMenu.php partial and just place an include inside it:

<?php include_partial('navigation/menu', array('menu' => 'Entity Type', 'other_var' => $other_var) ?>

Where each of your variables will need to be passed to the partial as in $other_var. Does this at least solve the problem?

Upvotes: 3

Related Questions