A factory is the definition of a class for a certain task. Symfony relies on factories for its core features such as the controller and session capabilities. For instance, when the framework needs to create a new request object, it searches in the factory definition for the name of the class to use for that purpose. The default factory definition for requests is sfWebRequest, so symfony creates an object of this class in order to deal with requests. The great advantage of using a factory definition is that it is very easy to alter the core features of the framework: Just change the factory definition, and symfony will use your custom request class instead of its own.

The factory definitions are stored in the factories.yml configuration file. Listing 17-7 shows the default factory definition file. Each definition is made of the name of an autoloaded class and (optionally) a set of parameters. For instance, the session storage factory (set under the storage: key) uses a session_name parameter to name the cookie created on the client computer to allow persistent sessions.

Listing 17-7 - Default Factories File, in frontend/config/factories.yml

-
  prod:
    logger:
      class:   sfNoLogger
      param:
        level:   err
        loggers: ~

  cli:
    controller:
      class: sfConsoleController
    request:
      class: sfConsoleRequest
    response:
      class: sfConsoleResponse

  test:
    storage:
      class: sfSessionTestStorage
      param:
        session_path: %SF_TEST_CACHE_DIR%/sessions

    response:
      class: sfWebResponse
      param:
        send_http_headers: false

  all:
    routing:
      class: sfPatternRouting
      param:
        generate_shortest_url:            true
        extra_parameters_as_query_string: true

  #all:
  #  controller:
  #    class: sfFrontWebController
  #
  #  request:
  #    class: sfWebRequest
  #    param:
  #      logging:           %SF_LOGGING_ENABLED%
  #      path_info_array:   SERVER
  #      path_info_key:     PATH_INFO
  #      relative_url_root: ~
  #      formats:
  #        txt:  text/plain
  #        js:   [application/javascript, application/x-javascript, text/javascript]
  #        css:  text/css
  #        json: [application/json, application/x-json]
  #        xml:  [text/xml, application/xml, application/x-xml]
  #        rdf:  application/rdf+xml
  #        atom: application/atom+xml
  #
  #  response:
  #    class: sfWebResponse
  #    param:
  #      logging:           %SF_LOGGING_ENABLED%
  #      charset:           %SF_CHARSET%
  #      send_http_headers: true
  #
  #  user:
  #    class: myUser
  #    param:
  #      timeout:         1800
  #      logging:         %SF_LOGGING_ENABLED%
  #      use_flash:       true
  #      default_culture: %SF_DEFAULT_CULTURE%
  #
  #  storage:
  #    class: sfSessionStorage
  #    param:
  #      session_name: symfony
  #
  #  view_cache:
  #    class: sfFileCache
  #    param:
  #      automatic_cleaning_factor: 0
  #      cache_dir:                 %SF_TEMPLATE_CACHE_DIR%
  #      lifetime:                  86400
  #      prefix:                    %SF_APP_DIR%/template
  #
  #  i18n:
  #    class: sfI18N
  #    param:
  #      source:               XLIFF
  #      debug:                off
  #      untranslated_prefix:  "[T]"
  #      untranslated_suffix:  "[/T]"
  #      cache:
  #        class: sfFileCache
  #        param:
  #          automatic_cleaning_factor: 0
  #          cache_dir:                 %SF_I18N_CACHE_DIR%
  #          lifetime:                  31556926
  #          prefix:                    %SF_APP_DIR%/i18n
  #
  #  routing:
  #    class: sfPatternRouting
  #    param:
  #      load_configuration:               true
  #      suffix:                           ''
  #      default_module:                   default
  #      default_action:                   index
  #      debug:                            %SF_DEBUG%
  #      logging:                          %SF_LOGGING_ENABLED%
  #      generate_shortest_url:            false
  #      extra_parameters_as_query_string: false
  #      cache:
  #        class: sfFileCache
  #        param:
  #          automatic_cleaning_factor: 0
  #          cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
  #          lifetime:                  31556926
  #          prefix:                    %SF_APP_DIR%/routing
  #
  #  logger:
  #    class: sfAggregateLogger
  #    param:
  #      level: debug
  #      loggers:
  #        sf_web_debug:
  #          class: sfWebDebugLogger
  #          param:
  #            level: debug
  #            condition:       %SF_WEB_DEBUG%
  #            xdebug_logging:  true
  #            web_debug_class: sfWebDebug
  #        sf_file_debug:
  #          class: sfFileLogger
  #          param:
  #            level: debug
  #            file: %SF_LOG_DIR%/%SF_APP%_%SF_ENVIRONMENT%.log

The best way to change a factory is to create a new class inheriting from the default factory and to add new methods to it. For instance, the user session factory is set to the myUser class (located in frontend/lib/) and inherits from sfUser. Use the same mechanism to take advantage of the existing factories. Listing 17-8 shows an example of a new factory for the request object.

Listing 17-8 - Overriding Factories

// Create a myRequest.class.php in an autoloaded directory,
// For instance in frontend/lib/
<?php

class myRequest extends sfRequest
{
  // Your code here
}

// Declare this class as the request factory in factories.yml
all:
  request:
    class: myRequest