Posts Tagged sfCrossAppControllerPlugin

Hyperlink Between Application in Symfony 1.1

Symfony 1.1 introduce a new class named sfApplicationConfiguration which replace flat application front controller script into object oriented way. One of the benefit of this class is used to hyperlink between application. Now hyperlink between aplication using symfony internal routing name is possible. This is hard to achieve in previous symfony release–symfony 1.0–hyperlink must be in absolute form.
This feature is not available out of the box, so we must do a little hack to use it. The idea is, switch to the desired application to generate the route.

Code:

<?php

class sfCrossAppController extends sfFrontWebController
{
  const
    CROSS_APP_URL_SPLITER       = '|';

  public function genUrl($parameters = array(), $absolute = false)
  {
    if (!is_array($parameters) && false !== strpos($parameters, self::CROSS_APP_URL_SPLITER))
    {
      list($app, $parameters) = explode(self::CROSS_APP_URL_SPLITER, $parameters, 2);
      if ($app !== ($oldApp = sfConfig::get('sf_app')))
      {
        $environment    = sfConfig::get('sf_environment');
        $no_script_name = sfConfig::get('sf_no_script_name');

        // application paths
        $app_paths      = sfConfig::get('app_sf_cross_app_controller_plugin_app_paths', array());
        $old_app_path   = isset($app_paths[$oldApp]) ? $app_paths[$oldApp] : '';
        $app_path       = isset($app_paths[$app]) ? $app_paths[$app] : '';
        $message        = null;

        // save all configs, switchTo() clear it
        $configs = sfConfig::getAll();

        // switch to desired application
        sfContext::switchTo($app);
        try
        {
          $context    = sfContext::getInstance();
          $controller = $context->getController();
          $request    = $context->getRequest();

          $parameters = $controller->genUrl($parameters, true);

          $replace    = '';
          $with       = '';
          if (!$no_script_name)
          {
            $replace .= $oldApp.'_'.$environment.'.php';
            $with    .= $app.'_'.$environment.'.php';
          }

          // replace script name, url generation always using current script name
          $replace    = $request->getHost().$old_app_path.(substr($old_app_path, -1) !== '/' ? '/' : '').$replace;
          $with       = $request->getHost().$app_path.(substr($app_path, -1) !== '/' ? '/' : '').$with;
          $parameters = str_replace($replace, $with, $parameters);
        }
        catch (sfException $e)
        {
          $message = $e->getMessage();
        }

        // switch back to original application
        sfContext::switchTo($oldApp);
        sfConfig::add($configs);

        // log any error message
        if (!is_null($message) && sfConfig::get('sf_logging_enabled'))
        {
          sfContext::getInstance()->getEventDispatcher()->notify(new sfEvent($this, 'application.log', array($message, 'priority' => sfLogger::ERR)));
        }
      }
    }

    return parent::genUrl($parameters, $absolute);
  }
}

To configure this plugin, we need to changes the controller class to sfCrossAppController in all our applications factories.yml.

all:
  controller:
    class: sfCrossAppController

Next, we may configure the path of applications, we can put in app.yml in the config directory of the project (project/config/app.yml).

all:
  sf_cross_app_controller_plugin:
    app_paths:
      frontend: /
      backend:  /admin/
      other:    /other/

This settings is actually needed to generate url for production when sf_no_script_name is set to on.
We define a cross application routing with this pattern app|routing, for example frontend|@homepage will generate the homepage routing of frontend application.
Now all builtin symfony helper which accept internal route (@route or module/action) can be prefixed with app and separated by | to point to the route of app application.

Download here:
Symfony 1.1: sfCrossAppControllerPlugin.zip
Symfony 1.2: sfCrossAppControllerPlugin.zip

, ,

19 Comments