Business

Technology

 

 

 

 

 

The number one benefit of information technology is that it empowers people to do what they want to do. It lets people be creative. It lets people be productive. It lets people learn things they didn't think they could learn before, and so in a sense it is all about potential.

Steve Ballmer

Symfony: Execution Filters: Controlling output

Looking for a Symfony Developer?

If you or your company are looking for a Symfony Developer contact us or read about our Symfony Development Service

Symfony: Execution Filters: Controlling output key visual

This is the last in a three part article on Symfony Request filters. Here we look at using a filter change the output after the main logic is run. This article is split up into 3 parts.

  1. Symfony: Execution Filters - Here I show you what is needed to set up the filter and an overview as to whats going on,
  2. Symfony: Execution Filters: Add objects to global environment - Here we look at using a filter to add objects into the global environment before the main logic is run.
  3. Symfony: Execution Filters: Controlling output - This; Here we look at using a filter to modify the output of an action before sending the request off to the view.

Overview

In the Time Tracker application companies are permitted brand there instances with different layouts, css, javascript, images and so on. The obvious way to do achieve this is to call the setLayout() method in each action. However with over close to 100 actions this would really bulk up the code and distract from the application and business logic. Instead the sfExecutionFilter was overridden and the default layout was swapped with the companies requested layout. Read on to see how it is done.

Creating the post execution filter

This filter takes advantage of the CompanyContextFilter presented in the previous article to select the companies desired layout.

We will be creating a filter that overrides the sfExecutionFilter's executeView method. This is done by:

  1. Create a filter that extends sfExecutionFilter,
  2. Reading the company object out of sfContext,
  3. Setting the layout to the companies requested layout if present, and finally
  4. Register the filter

Extending sfFilter

In the application's lib directory "$site/apps/frontend/lib" create a file called CompanyLayoutFilter.class.php.

Open this new file and add the following code

<?php

// $site/apps/frontend/lib/CompanyContextFilter.class.php
class CompanyLayoutFilter extends sfExecutionFilter
{

  protected function executeView($moduleName, $actionName, $viewName, $viewAttributes)
  {
    $request = $this->context->getRequest();
  	
    $controller = $this->context->getController();

    // get the view instance
    $view = $controller->getView($moduleName, $actionName, $viewName);

    if($this->context->has('Company')){
      $layout = $this->context->get('Company')->getLayout();
      if(file_exists($layout) && !$request->isXmlHttpRequest()){
        $view->setDecoratorTemplate($layout);
      }
    }
    
    // execute the view
    $view->execute();

  }
}

This code is taken from the Time Tracker application's api "application", modified for readability. Here is a break down:

  • Line 9-14: Sets up required objects
  • Line 16: Ensure that we do in-fact have a company object in context
  • Line 17: Gets the layout file for the company 
  • Line 18: Ensures the file exists
  • Line 18: Sets the layout for the view to use
  • Line 24: Executes the view

Now the actions can continue to focus on their key task and the view remains seperate.

Register the filter with Symfony

The next step is to register the filter with Symfony. This is simply a matter of opening the application's filters.yml file and telling symfony to use a different execution filter

# $site/apps/api/config/filters.yml

rendering: ~
security:  ~

cache:     ~
execution:
  class:  CompanyLayoutFilter

 

Read back: Symfony: Execution Filters:Add objects to global environment

If you found this article useful, please be sure to check out the related articles below.

Jonathan commented:

A great article on an under documented feature of Symfony, thanks!

gopi commented:

tried it.  doesnt seem to be working.

Adam Pullen commented:

Hello gopi,

Thanks for your comment.

What doesn't seem to be working?

Is the filter even being executed?
Can you add a die("hello from filter") to the filter?
 

gopi commented:

yes, filter is being executed.

what I see is by enabling this filter, no layout is getting set. I even commented out the $view->setDecorator() to check that it should show default layout.

but it is always showing without any layout.  not sure what I am missing.

Adam Pullen commented:

I trust that

* your calling $view->execute().

* you havn't set layout(false) anywhere in your action,

* your layout file is accessable (needs to be the full path to the file)

gopi commented:

adam, thx for your response.

I copied ur code as and commented out the setlayout part (given below).

I expected this to be a pass through filter with the default view and layout handle to happen.

but all I am seeing is symfony's debug log and nothing else.

---------------

class ViewFilter extends sfExecutionFilter
{

  protected function executeView($moduleName, $actionName, $viewName, $viewAttributes)
  {
    $request = $this->context->getRequest();
     
    $controller = $this->context->getController();

    // get the view instance
    $view = $controller->getView($moduleName, $actionName, $viewName);
    /*
    if($this->context->has('Company')){
      $layout = $this->context->get('Company')->getLayout();
      if(file_exists($layout) && !$request->isXmlHttpRequest()){
        $view->setDecoratorTemplate($layout);
      }
    } */
 
    // execute the view
    $view->execute();

  }
}

Adam Pullen commented:

Ok, Silly question, 

1) did you set the layout file in the config?

2) Is there anything in the layout file to render?

gopi commented:

1. yes, I did set the layout in the view config, which is the default.. looks like

  has_layout:     true
  layout:         layout

2. yes, if I just remove the filter setting line from filter.yml,  I get the normal ui output

Tristan commented:

Hi Gopi,

This is what I added to executeView() to make it work in Symfony 1.4.X (taken directly from sfExecutionFilter.class.php):

// Code setting the decorator, etc goes here

// execute the view
$view->execute()

$view->getAttributeHolder()->add($viewAttributes);

// render the view
switch ($controller->getRenderMode())
{
  case sfView::RENDER_NONE:
    break;

  case sfView::RENDER_CLIENT:
    $viewData = $view->render();
    $this->context->getResponse()->setContent($viewData);
    break;

  case sfView::RENDER_VAR:
    $viewData = $view->render();
    $controller->getActionStack()->getLastEntry()->setPresentation($viewData);
    break;
}
 

gopi commented:

thx Tristan, I will try it later in the day and post back

gopi commented:

tristan,

I tried it a month back and it WORKS!

forgot to update before, apologies..

many thanks for ur help

--gopi

Add a comment

*
*
Your email will not be published
*
*