Una factoría consiste en la definición de una clase que realiza una determinada tarea. Symfony utiliza las factorias en su funcionamiento interno, como por ejemplo para los controladores y para las sesiones. Cuando el framework necesita por ejemplo crear un nuevo objeto para una petición, busca en la definición de la factoría el nombre de la clase que se debe utilizar para esta tarea. Como la definición por defecto de la factoría para las peticiones es sfWebRequest, Symfony crea un objeto de esta clase para tratar con las peticiones. La principal ventaja de utilizar las definiciones de las factorías es que es muy sencillo modificar las características internas de Symfony: simplemente es necesario modificar la definición de la factoría y Symfony utiliza la clase propia indicada en vez de la clase por defecto.

Las definiciones para las factorías se guardan en el archivo de configuración factories.yml. El listado 17-7 muestra el contenido por defecto de ese archivo. Cada definición consta del nombre de una clase y opcionalmente, de una serie de parámetros. Por ejemplo, la factoría para el almacenamiento de la sesión (que se indica bajo la clave storage:) utiliza un parámetro llamado session_name para establecer el nombre de la cookie que se crea para el lado del cliente, de forma que se puedan realizar sesiones persistentes.

Listado 17-7 - Archivo por defecto para las factorias, en 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

La mejor forma de crear una nueva factoría consiste en crear una nueva clase que herede de la clase por defecto y añadirle nuevos métodos. La factoría para las sesiones de usuario se establece a la clase myUser (localizada en frontend/lib) y hereda de la clase sfUser. Se puede utilizar el mismo mecanismo para aprovechar las factorías ya existentes. El listado 17-8 muestra el ejemplo de una factoría para el objeto de la petición.

Listado 17-8 - Redefiniendo factorías

// Se crea la clase miRequest.class.php en un directorio para
// el que esté activada la carga automática de clases, por ejemplo
// frontend/lib/
<?php

class miRequest extends sfRequest
{
  // El código de la nueva factoría
}
# Se declara en el archivo factories.yml que esta nueva
# clase es la factoría para las peticiones
all:
  request:
    class: miRequest