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

#all:
#  controller:
#    class: sfFrontWebController
#
#  request:
#    class: sfWebRequest
#    param:
#      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%
#
#  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%
#
#  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:                  86400
#          prefix:                    %SF_APP_DIR%
#
#  routing:
#    class: sfPatternRouting
#    param:
#      load_configuration: true
#      suffix:             .
#      default_module:     default
#      default_action:     index
#      variable_prefixes:  [':']
#      segment_separators: ['/', '.']
#      variable_regex:     '[\w\d_]+'
#      debug:              %SF_DEBUG%
#      logging:            %SF_LOGGING_ENABLED%
#      cache:
#        class: sfFileCache
#        param:
#          automatic_cleaning_factor: 0
#          cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
#          lifetime:                  31556926
#          prefix:                    %SF_APP_DIR%
#
#  logger:
#    class: sfAggregateLogger
#    param:
#      level: debug
#      loggers:
#        sf_web_debug:
#          class: sfWebDebugLogger
#          param:
#            condition:      %SF_WEB_DEBUG%
#            xdebug_logging: true
#        sf_file_debug:
#          class: sfFileLogger
#          param:
#            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