From a24cbb507550c0384146f0741fab53e7ad183656 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 19 Apr 2016 15:59:24 +0200 Subject: [PATCH] Revert "minor #6479 Update php.rst (carlos-granados)" This reverts commit fefc8a0426b6a438d7132b3035b1f5e0fab90a42, reversing changes made to 7819f9e0fb24df69ba382a11be75a2c157c97388. --- best_practices/business-logic.rst | 6 +- best_practices/configuration.rst | 4 +- best_practices/creating-the-project.rst | 56 +- best_practices/forms.rst | 66 +- best_practices/i18n.rst | 6 +- best_practices/introduction.rst | 4 + best_practices/security.rst | 235 +----- best_practices/tests.rst | 4 +- best_practices/web-assets.rst | 2 - book/bundles.rst | 3 +- book/configuration.rst | 6 +- book/controller.rst | 68 +- book/doctrine.rst | 82 +- book/forms.rst | 288 ++++--- book/from_flat_php_to_symfony2.rst | 6 +- book/http_cache.rst | 21 +- book/http_fundamentals.rst | 4 +- .../_service_container_my_mailer.rst.inc | 35 - book/installation.rst | 66 +- book/page_creation.rst | 55 +- book/performance.rst | 20 +- book/routing.rst | 132 +-- book/security.rst | 154 +--- book/service_container.rst | 246 ++---- book/templating.rst | 139 ++-- book/testing.rst | 86 +- book/translation.rst | 234 +----- book/validation.rst | 26 +- changelog.rst | 511 +----------- components/asset/index.rst | 7 - components/asset/introduction.rst | 324 -------- .../class_loader/cache_class_loader.rst | 6 + components/class_loader/class_loader.rst | 6 +- .../class_loader/debug_class_loader.rst | 20 +- components/class_loader/index.rst | 7 +- components/class_loader/introduction.rst | 17 +- components/class_loader/psr4_class_loader.rst | 63 -- components/config/definition.rst | 24 +- .../console/changing_default_command.rst | 63 -- components/console/events.rst | 35 +- .../console/helpers/debug_formatter.rst | 142 ---- components/console/helpers/dialoghelper.rst | 293 ++++++- components/console/helpers/index.rst | 5 - components/console/helpers/map.rst.inc | 8 +- components/console/helpers/processhelper.rst | 81 -- components/console/helpers/progressbar.rst | 323 -------- components/console/helpers/progresshelper.rst | 80 +- components/console/helpers/questionhelper.rst | 314 -------- components/console/helpers/table.rst | 233 ------ components/console/helpers/tablehelper.rst | 53 +- components/console/index.rst | 2 - components/console/introduction.rst | 46 +- components/console/logger.rst | 106 --- components/css_selector.rst | 7 +- .../{debug/introduction.rst => debug.rst} | 9 +- components/debug/class_loader.rst | 18 - components/debug/index.rst | 8 - components/dependency_injection/advanced.rst | 224 ------ .../dependency_injection/autowiring.rst | 405 ---------- .../dependency_injection/compilation.rst | 111 +-- components/dependency_injection/factories.rst | 111 +-- components/dependency_injection/index.rst | 1 - .../dependency_injection/lazy_services.rst | 5 +- .../dependency_injection/parentservices.rst | 3 +- components/dependency_injection/tags.rst | 21 +- components/dom_crawler.rst | 96 +-- .../event_dispatcher/immutable_dispatcher.rst | 3 + components/event_dispatcher/introduction.rst | 29 +- .../event_dispatcher/traceable_dispatcher.rst | 4 +- components/expression_language/caching.rst | 74 -- components/expression_language/extending.rst | 126 --- components/expression_language/index.rst | 10 - .../expression_language/introduction.rst | 115 --- components/expression_language/syntax.rst | 310 -------- .../introduction.rst => filesystem.rst} | 22 +- components/filesystem/index.rst | 8 - components/filesystem/lock_handler.rst | 82 -- components/finder.rst | 10 + components/form/form_events.rst | 41 +- components/form/introduction.rst | 163 ++-- components/form/type_guesser.rst | 20 +- components/http_foundation/introduction.rst | 76 +- .../http_foundation/trusting_proxies.rst | 4 + components/http_kernel/introduction.rst | 30 +- components/index.rst | 8 +- components/intl.rst | 85 ++ components/map.rst.inc | 37 +- components/options_resolver.rst | 750 ++++++------------ components/phpunit_bridge.rst | 246 ------ components/process.rst | 87 +- components/property_access/introduction.rst | 39 +- components/routing/hostname_pattern.rst | 3 + components/routing/introduction.rst | 4 + components/security/authentication.rst | 11 +- components/security/authorization.rst | 26 +- components/security/firewall.rst | 24 +- components/security/introduction.rst | 18 - components/security/secure_tools.rst | 4 +- components/serializer.rst | 534 ++----------- components/stopwatch.rst | 14 +- .../templating/helpers/assetshelper.rst | 24 - components/translation/custom_formats.rst | 12 +- components/translation/introduction.rst | 10 +- components/translation/usage.rst | 27 - components/var_dumper/advanced.rst | 242 ------ components/var_dumper/index.rst | 8 - components/var_dumper/introduction.rst | 274 ------- components/yaml/introduction.rst | 13 +- contributing/code/core_team.rst | 4 +- contributing/code/patches.rst | 8 +- contributing/code/security.rst | 8 - contributing/documentation/standards.rst | 4 - .../assetic/_standard_edition_warning.inc | 5 - cookbook/assetic/apply_to_option.rst | 2 - cookbook/assetic/asset_management.rst | 91 +-- cookbook/assetic/index.rst | 2 - cookbook/assetic/jpeg_optimize.rst | 2 - cookbook/assetic/php.rst | 6 +- cookbook/assetic/uglifyjs.rst | 2 - cookbook/assetic/yuicompressor.rst | 2 - cookbook/bundles/installation.rst | 4 +- cookbook/bundles/override.rst | 15 +- cookbook/bundles/remove.rst | 3 +- cookbook/configuration/apache_router.rst | 135 +++- .../configuration_organization.rst | 21 +- cookbook/configuration/environments.rst | 24 +- .../front_controllers_and_kernel.rst | 8 +- cookbook/configuration/index.rst | 1 - cookbook/configuration/micro-kernel-trait.rst | 321 -------- .../configuration/override_dir_structure.rst | 42 +- cookbook/console/command_in_controller.rst | 23 +- cookbook/console/commands_as_services.rst | 184 ----- cookbook/console/console_command.rst | 82 +- cookbook/console/index.rst | 2 - cookbook/console/logging.rst | 5 +- cookbook/console/request_context.rst | 9 +- cookbook/console/style.rst | 376 --------- cookbook/console/usage.rst | 37 +- cookbook/controller/error_pages.rst | 86 +- cookbook/controller/service.rst | 13 +- cookbook/controller/upload_file.rst | 10 +- cookbook/debugging.rst | 29 +- cookbook/deployment/azure-website.rst | 18 +- cookbook/deployment/heroku.rst | 2 +- cookbook/deployment/platformsh.rst | 8 +- cookbook/deployment/tools.rst | 6 +- cookbook/doctrine/console.rst | 6 +- .../doctrine/event_listeners_subscribers.rst | 7 - cookbook/doctrine/file_uploads.rst | 10 +- cookbook/doctrine/mapping_model_classes.rst | 62 +- .../doctrine/multiple_entity_managers.rst | 8 +- cookbook/doctrine/pdo_session_storage.rst | 198 +++-- cookbook/doctrine/registration_form.rst | 40 +- cookbook/doctrine/reverse_engineering.rst | 6 +- cookbook/email/email.rst | 16 +- cookbook/email/spool.rst | 6 +- cookbook/email/testing.rst | 4 +- .../event_dispatcher/before_after_filters.rst | 8 +- cookbook/event_dispatcher/event_listener.rst | 21 +- cookbook/expression/expressions.rst | 106 --- cookbook/expression/index.rst | 7 - cookbook/form/create_custom_field_type.rst | 94 ++- cookbook/form/create_form_type_extension.rst | 69 +- cookbook/form/data_transformers.rst | 119 +-- cookbook/form/direct_submit.rst | 52 +- cookbook/form/dynamic_form_modification.rst | 155 ++-- cookbook/form/form_collections.rst | 45 +- cookbook/form/form_customization.rst | 68 +- cookbook/form/inherit_data_option.rst | 37 +- cookbook/form/unit_testing.rst | 102 +-- cookbook/form/use_empty_data.rst | 24 +- cookbook/form/use_virtuals_forms.rst | 7 +- cookbook/index.rst | 2 +- cookbook/logging/channels_handlers.rst | 10 +- cookbook/logging/index.rst | 1 - cookbook/logging/monolog.rst | 10 +- cookbook/logging/monolog_console.rst | 185 ----- cookbook/logging/monolog_email.rst | 8 + .../logging/monolog_regex_based_excludes.rst | 5 + cookbook/map.rst.inc | 27 +- cookbook/profiler/matchers.rst | 18 +- cookbook/profiler/profiling_data.rst | 6 +- cookbook/profiler/storage.rst | 41 +- .../request/load_balancer_reverse_proxy.rst | 3 + cookbook/request/mime_type.rst | 139 ++-- cookbook/routing/method_parameters.rst | 26 +- .../_ircmaxwell_password-compat.rst.inc | 8 + cookbook/security/_supportsToken.rst.inc | 10 - cookbook/security/access_control.rst | 53 +- cookbook/security/acl.rst | 10 +- cookbook/security/acl_advanced.rst | 8 - cookbook/security/api_key_authentication.rst | 711 ----------------- cookbook/security/csrf_in_login_form.rst | 18 +- .../custom_authentication_provider.rst | 58 +- .../custom_password_authenticator.rst | 259 ------ cookbook/security/entity_provider.rst | 43 +- cookbook/security/firewall_restriction.rst | 185 ----- cookbook/security/form_login.rst | 2 +- cookbook/security/form_login_setup.rst | 19 +- cookbook/security/guard-authentication.rst | 579 -------------- cookbook/security/host_restriction.rst | 6 - cookbook/security/impersonating_user.rst | 15 +- cookbook/security/index.rst | 8 - .../multiple_guard_authenticators.rst | 172 ---- cookbook/security/named_encoders.rst | 124 --- cookbook/security/pre_authenticated.rst | 71 +- cookbook/security/remember_me.rst | 31 +- cookbook/security/securing_services.rst | 53 +- cookbook/security/user_checkers.rst | 212 ----- cookbook/security/voters.rst | 360 +++------ cookbook/serializer.rst | 147 +--- .../service_container/compiler_passes.rst | 26 +- cookbook/service_container/index.rst | 2 +- cookbook/service_container/scopes.rst | 340 ++++++++ cookbook/service_container/shared.rst | 44 - cookbook/session/index.rst | 3 +- cookbook/session/limit_metadata_writes.rst | 65 -- cookbook/session/locale_sticky_session.rst | 9 +- cookbook/session/php_bridge.rst | 3 + cookbook/symfony1.rst | 371 +++++++++ cookbook/templating/PHP.rst | 19 +- cookbook/templating/namespaced_paths.rst | 10 + .../templating/render_without_controller.rst | 4 + cookbook/templating/twig_extension.rst | 10 + cookbook/testing/bootstrap.rst | 8 +- cookbook/testing/database.rst | 13 +- cookbook/testing/doctrine.rst | 18 +- cookbook/testing/insulating_clients.rst | 8 +- cookbook/testing/profiling.rst | 6 +- .../testing/simulating_authentication.rst | 4 +- cookbook/validation/custom_constraint.rst | 30 +- cookbook/validation/index.rst | 1 - cookbook/validation/severity.rst | 162 ---- cookbook/web_server/built_in.rst | 68 +- cookbook/workflow/new_project_svn.rst | 13 +- create_framework/dependency_injection.rst | 5 +- create_framework/http_foundation.rst | 2 +- create_framework/introduction.rst | 6 +- images/book/doctrine_web_debug_toolbar.png | Bin 44166 -> 82133 bytes images/book/security_anonymous_wdt.png | Bin 9302 -> 26288 bytes images/book/symfony_loggedin_wdt.png | Bin 11478 -> 21855 bytes images/book/translation/debug_1.png | Bin 22689 -> 0 bytes images/book/translation/debug_2.png | Bin 22534 -> 0 bytes images/book/translation/debug_3.png | Bin 22381 -> 0 bytes images/book/translation/debug_4.png | Bin 22236 -> 0 bytes images/components/console/debug_formatter.png | Bin 178248 -> 0 bytes .../console/process-helper-debug.png | Bin 28822 -> 0 bytes .../console/process-helper-error-debug.png | Bin 19108 -> 0 bytes .../console/process-helper-verbose.png | Bin 14289 -> 0 bytes images/components/console/progressbar.gif | Bin 29016 -> 0 bytes images/components/phpunit_bridge/report.png | Bin 47710 -> 0 bytes images/components/var_dumper/01-simple.png | Bin 16430 -> 0 bytes .../var_dumper/02-multi-line-str.png | Bin 24225 -> 0 bytes images/components/var_dumper/03-object.png | Bin 23741 -> 0 bytes .../var_dumper/04-dynamic-property.png | Bin 19184 -> 0 bytes images/components/var_dumper/05-soft-ref.png | Bin 20876 -> 0 bytes images/components/var_dumper/06-constants.png | Bin 33200 -> 0 bytes images/components/var_dumper/07-hard-ref.png | Bin 19436 -> 0 bytes .../var_dumper/08-virtual-property.png | Bin 32802 -> 0 bytes images/components/var_dumper/09-cut.png | Bin 32705 -> 0 bytes .../exceptions-in-dev-environment.png | Bin 97765 -> 131511 bytes images/quick_tour/hello_fabien.png | Bin 0 -> 89063 bytes images/quick_tour/profiler.png | Bin 75322 -> 888832 bytes images/quick_tour/web_debug_toolbar.png | Bin 51250 -> 89165 bytes images/quick_tour/welcome.png | Bin 49788 -> 66708 bytes images/reference/form/choice-example1.png | Bin 28958 -> 0 bytes images/reference/form/choice-example2.png | Bin 30469 -> 0 bytes images/reference/form/choice-example3.png | Bin 33817 -> 0 bytes images/reference/form/choice-example4.png | Bin 51730 -> 0 bytes images/reference/form/choice-example5.png | Bin 40125 -> 0 bytes quick_tour/the_architecture.rst | 20 +- redirection_map | 23 - reference/configuration/assetic.rst | 8 - reference/configuration/debug.rst | 75 -- reference/configuration/framework.rst | 601 +++++++------- reference/configuration/monolog.rst | 11 - reference/configuration/security.rst | 51 +- reference/configuration/twig.rst | 44 +- reference/configuration/web_profiler.rst | 4 - reference/constraints.rst | 6 +- reference/constraints/All.rst | 3 - reference/constraints/Bic.rst | 95 --- reference/constraints/Blank.rst | 3 - reference/constraints/Callback.rst | 199 ++--- reference/constraints/CardScheme.rst | 6 +- reference/constraints/Choice.rst | 3 - reference/constraints/Collection.rst | 7 +- reference/constraints/Count.rst | 3 - reference/constraints/Country.rst | 3 - reference/constraints/Currency.rst | 6 +- reference/constraints/Date.rst | 3 - reference/constraints/DateTime.rst | 3 - reference/constraints/Email.rst | 17 +- reference/constraints/EqualTo.rst | 6 +- reference/constraints/Expression.rst | 255 ------ reference/constraints/False.rst | 8 + reference/constraints/File.rst | 53 +- reference/constraints/GreaterThan.rst | 202 +---- reference/constraints/GreaterThanOrEqual.rst | 202 +---- reference/constraints/Iban.rst | 6 +- reference/constraints/IdenticalTo.rst | 6 +- reference/constraints/Image.rst | 182 +---- reference/constraints/Ip.rst | 3 - reference/constraints/IsFalse.rst | 3 - reference/constraints/IsNull.rst | 3 - reference/constraints/IsTrue.rst | 3 - reference/constraints/Isbn.rst | 65 +- reference/constraints/Issn.rst | 6 +- reference/constraints/Language.rst | 3 - reference/constraints/Length.rst | 3 - reference/constraints/LessThan.rst | 193 +---- reference/constraints/LessThanOrEqual.rst | 201 +---- reference/constraints/Locale.rst | 3 - reference/constraints/Luhn.rst | 6 +- reference/constraints/NotBlank.rst | 3 - reference/constraints/NotEqualTo.rst | 6 +- reference/constraints/NotIdenticalTo.rst | 6 +- reference/constraints/NotNull.rst | 3 - reference/constraints/Null.rst | 8 + reference/constraints/Range.rst | 219 ----- reference/constraints/Regex.rst | 6 +- reference/constraints/Time.rst | 3 - reference/constraints/True.rst | 8 + reference/constraints/Type.rst | 3 - reference/constraints/UniqueEntity.rst | 9 +- reference/constraints/Url.rst | 149 ---- reference/constraints/UserPassword.rst | 12 +- reference/constraints/Uuid.rst | 125 --- reference/constraints/Valid.rst | 11 +- reference/constraints/_payload-option.rst.inc | 13 - reference/constraints/map.rst.inc | 3 - reference/dic_tags.rst | 286 ++----- reference/events.rst | 31 - reference/forms/twig_reference.rst | 29 +- reference/forms/types.rst | 3 +- reference/forms/types/birthday.rst | 49 +- reference/forms/types/button.rst | 11 +- reference/forms/types/checkbox.rst | 22 +- reference/forms/types/choice.rst | 287 +++---- reference/forms/types/collection.rst | 106 +-- reference/forms/types/country.rst | 37 +- reference/forms/types/currency.rst | 40 +- reference/forms/types/date.rst | 52 +- reference/forms/types/datetime.rst | 51 +- reference/forms/types/email.rst | 22 +- reference/forms/types/entity.rst | 178 ++--- reference/forms/types/file.rst | 36 +- reference/forms/types/form.rst | 45 +- reference/forms/types/hidden.rst | 9 +- reference/forms/types/integer.rst | 45 +- reference/forms/types/language.rst | 39 +- reference/forms/types/locale.rst | 39 +- reference/forms/types/map.rst.inc | 63 +- reference/forms/types/money.rst | 32 +- reference/forms/types/number.rst | 62 +- reference/forms/types/options/action.rst.inc | 3 + reference/forms/types/options/attr.rst.inc | 2 +- .../forms/types/options/button_attr.rst.inc | 5 +- .../forms/types/options/by_reference.rst.inc | 17 +- .../types/options/cascade_validation.rst.inc | 20 + .../types/options/checkbox_empty_data.rst.inc | 2 +- .../forms/types/options/choice_attr.rst.inc | 26 - .../forms/types/options/choice_label.rst.inc | 56 -- .../forms/types/options/choice_name.rst.inc | 11 - .../options/choice_translation_domain.rst.inc | 12 - .../choice_type_translation_domain.rst.inc | 8 - .../forms/types/options/choice_value.rst.inc | 20 - reference/forms/types/options/data.rst.inc | 5 +- .../forms/types/options/data_class.rst.inc | 5 +- .../forms/types/options/date_format.rst.inc | 5 +- .../forms/types/options/disabled.rst.inc | 3 + .../forms/types/options/empty_data.rst.inc | 7 +- ...laceholder.rst.inc => empty_value.rst.inc} | 27 +- .../forms/types/options/error_mapping.rst.inc | 5 +- .../forms/types/options/group_by.rst.inc | 43 - reference/forms/types/options/html5.rst.inc | 10 - .../forms/types/options/inherit_data.rst.inc | 4 + .../types/options/invalid_message.rst.inc | 2 +- .../invalid_message_parameters.rst.inc | 2 +- .../forms/types/options/label_format.rst.inc | 47 -- .../forms/types/options/max_length.rst.inc | 10 + reference/forms/types/options/method.rst.inc | 3 + reference/forms/types/options/pattern.rst.inc | 18 + .../forms/types/options/precision.rst.inc | 9 + .../types/options/preferred_choices.rst.inc | 64 +- .../forms/types/options/property_path.rst.inc | 3 + .../forms/types/options/read_only.rst.inc | 7 + reference/forms/types/options/scale.rst.inc | 9 - .../forms/types/options/with_minutes.rst.inc | 3 + reference/forms/types/password.rst | 24 +- reference/forms/types/percent.rst | 29 +- reference/forms/types/radio.rst | 30 +- reference/forms/types/range.rst | 76 -- reference/forms/types/repeated.rst | 32 +- reference/forms/types/reset.rst | 11 +- reference/forms/types/search.rst | 20 +- reference/forms/types/submit.rst | 21 +- reference/forms/types/text.rst | 22 +- reference/forms/types/textarea.rst | 20 +- reference/forms/types/time.rst | 57 +- reference/forms/types/timezone.rst | 41 +- reference/forms/types/url.rst | 22 +- reference/index.rst | 1 - reference/map.rst.inc | 1 - reference/requirements.rst | 12 +- reference/twig_reference.rst | 86 +- 406 files changed, 5728 insertions(+), 17256 deletions(-) delete mode 100644 book/includes/_service_container_my_mailer.rst.inc delete mode 100644 components/asset/index.rst delete mode 100644 components/asset/introduction.rst delete mode 100644 components/class_loader/psr4_class_loader.rst delete mode 100644 components/console/changing_default_command.rst delete mode 100644 components/console/helpers/debug_formatter.rst delete mode 100644 components/console/helpers/processhelper.rst delete mode 100644 components/console/helpers/progressbar.rst delete mode 100644 components/console/helpers/questionhelper.rst delete mode 100644 components/console/helpers/table.rst delete mode 100644 components/console/logger.rst rename components/{debug/introduction.rst => debug.rst} (86%) delete mode 100644 components/debug/class_loader.rst delete mode 100644 components/debug/index.rst delete mode 100644 components/dependency_injection/autowiring.rst delete mode 100644 components/expression_language/caching.rst delete mode 100644 components/expression_language/extending.rst delete mode 100644 components/expression_language/index.rst delete mode 100644 components/expression_language/introduction.rst delete mode 100644 components/expression_language/syntax.rst rename components/{filesystem/introduction.rst => filesystem.rst} (92%) delete mode 100644 components/filesystem/index.rst delete mode 100644 components/filesystem/lock_handler.rst delete mode 100644 components/phpunit_bridge.rst delete mode 100644 components/var_dumper/advanced.rst delete mode 100644 components/var_dumper/index.rst delete mode 100644 components/var_dumper/introduction.rst delete mode 100644 cookbook/assetic/_standard_edition_warning.inc delete mode 100644 cookbook/configuration/micro-kernel-trait.rst delete mode 100644 cookbook/console/commands_as_services.rst delete mode 100644 cookbook/console/style.rst delete mode 100644 cookbook/expression/expressions.rst delete mode 100644 cookbook/expression/index.rst delete mode 100644 cookbook/logging/monolog_console.rst create mode 100644 cookbook/security/_ircmaxwell_password-compat.rst.inc delete mode 100644 cookbook/security/_supportsToken.rst.inc delete mode 100644 cookbook/security/api_key_authentication.rst delete mode 100644 cookbook/security/custom_password_authenticator.rst delete mode 100644 cookbook/security/firewall_restriction.rst delete mode 100644 cookbook/security/guard-authentication.rst delete mode 100644 cookbook/security/host_restriction.rst delete mode 100644 cookbook/security/multiple_guard_authenticators.rst delete mode 100644 cookbook/security/named_encoders.rst delete mode 100644 cookbook/security/user_checkers.rst create mode 100644 cookbook/service_container/scopes.rst delete mode 100644 cookbook/service_container/shared.rst delete mode 100644 cookbook/session/limit_metadata_writes.rst create mode 100644 cookbook/symfony1.rst delete mode 100644 cookbook/validation/severity.rst delete mode 100644 images/book/translation/debug_1.png delete mode 100644 images/book/translation/debug_2.png delete mode 100644 images/book/translation/debug_3.png delete mode 100644 images/book/translation/debug_4.png delete mode 100644 images/components/console/debug_formatter.png delete mode 100644 images/components/console/process-helper-debug.png delete mode 100644 images/components/console/process-helper-error-debug.png delete mode 100644 images/components/console/process-helper-verbose.png delete mode 100644 images/components/console/progressbar.gif delete mode 100644 images/components/phpunit_bridge/report.png delete mode 100644 images/components/var_dumper/01-simple.png delete mode 100644 images/components/var_dumper/02-multi-line-str.png delete mode 100644 images/components/var_dumper/03-object.png delete mode 100644 images/components/var_dumper/04-dynamic-property.png delete mode 100644 images/components/var_dumper/05-soft-ref.png delete mode 100644 images/components/var_dumper/06-constants.png delete mode 100644 images/components/var_dumper/07-hard-ref.png delete mode 100644 images/components/var_dumper/08-virtual-property.png delete mode 100644 images/components/var_dumper/09-cut.png create mode 100644 images/quick_tour/hello_fabien.png delete mode 100644 images/reference/form/choice-example1.png delete mode 100644 images/reference/form/choice-example2.png delete mode 100644 images/reference/form/choice-example3.png delete mode 100644 images/reference/form/choice-example4.png delete mode 100644 images/reference/form/choice-example5.png delete mode 100644 reference/configuration/debug.rst delete mode 100644 reference/constraints/Bic.rst delete mode 100644 reference/constraints/Expression.rst create mode 100644 reference/constraints/False.rst create mode 100644 reference/constraints/Null.rst create mode 100644 reference/constraints/True.rst delete mode 100644 reference/constraints/Uuid.rst delete mode 100644 reference/constraints/_payload-option.rst.inc create mode 100644 reference/forms/types/options/cascade_validation.rst.inc delete mode 100644 reference/forms/types/options/choice_attr.rst.inc delete mode 100644 reference/forms/types/options/choice_label.rst.inc delete mode 100644 reference/forms/types/options/choice_name.rst.inc delete mode 100644 reference/forms/types/options/choice_translation_domain.rst.inc delete mode 100644 reference/forms/types/options/choice_type_translation_domain.rst.inc delete mode 100644 reference/forms/types/options/choice_value.rst.inc rename reference/forms/types/options/{placeholder.rst.inc => empty_value.rst.inc} (51%) delete mode 100644 reference/forms/types/options/group_by.rst.inc delete mode 100644 reference/forms/types/options/html5.rst.inc delete mode 100644 reference/forms/types/options/label_format.rst.inc create mode 100644 reference/forms/types/options/max_length.rst.inc create mode 100644 reference/forms/types/options/pattern.rst.inc create mode 100644 reference/forms/types/options/precision.rst.inc create mode 100644 reference/forms/types/options/read_only.rst.inc delete mode 100644 reference/forms/types/options/scale.rst.inc delete mode 100644 reference/forms/types/range.rst diff --git a/best_practices/business-logic.rst b/best_practices/business-logic.rst index 55305165436..3f1022a10d1 100644 --- a/best_practices/business-logic.rst +++ b/best_practices/business-logic.rst @@ -21,8 +21,6 @@ Inside here, you can create whatever directories you want to organize things: │ └─ AppBundle/ │ └─ Utils/ │ └─ MyClass.php - ├─ tests/ - ├─ var/ ├─ vendor/ └─ web/ @@ -42,8 +40,6 @@ and put things there: │ │ └─ Utils/ │ │ └─ MyClass.php │ └─ AppBundle/ - ├─ tests/ - ├─ var/ ├─ vendor/ └─ web/ @@ -322,7 +318,7 @@ command: .. code-block:: bash - $ php bin/console doctrine:fixtures:load + $ php app/console doctrine:fixtures:load Careful, database will be purged. Do you want to continue Y/N ? Y > purging database diff --git a/best_practices/configuration.rst b/best_practices/configuration.rst index 1bfa758b8a8..76aac62de31 100644 --- a/best_practices/configuration.rst +++ b/best_practices/configuration.rst @@ -52,8 +52,8 @@ Canonical Parameters Define all your application's parameters in the ``app/config/parameters.yml.dist`` file. -Symfony includes a configuration file called ``parameters.yml.dist``, which -stores the canonical list of configuration parameters for the application. +Since version 2.3, Symfony includes a configuration file called ``parameters.yml.dist``, +which stores the canonical list of configuration parameters for the application. Whenever a new configuration parameter is defined for the application, you should also add it to this file and submit the changes to your version control diff --git a/best_practices/creating-the-project.rst b/best_practices/creating-the-project.rst index 06e277b8cb6..45dcc987220 100644 --- a/best_practices/creating-the-project.rst +++ b/best_practices/creating-the-project.rst @@ -27,6 +27,7 @@ to create files and execute the following commands: .. code-block:: bash + # Linux, Mac OS X $ cd projects/ $ symfony new blog @@ -62,18 +63,13 @@ number of files and directories generated automatically: blog/ ├─ app/ + │ ├─ console + │ ├─ cache/ │ ├─ config/ + │ ├─ logs/ │ └─ Resources/ - ├─ bin - │ └─ console ├─ src/ │ └─ AppBundle/ - ├─ var/ - │ ├─ cache/ - │ ├─ logs/ - │ └─ sessions/ - ├─ tests/ - │ └─ AppBundle/ ├─ vendor/ └─ web/ @@ -81,16 +77,13 @@ This file and directory hierarchy is the convention proposed by Symfony to structure your applications. The recommended purpose of each directory is the following: +* ``app/cache/``, stores all the cache files generated by the application; * ``app/config/``, stores all the configuration defined for any environment; +* ``app/logs/``, stores all the log files generated by the application; * ``app/Resources/``, stores all the templates and the translation files for the application; * ``src/AppBundle/``, stores the Symfony specific code (controllers and routes), your domain code (e.g. Doctrine classes) and all your business logic; -* ``var/cache/``, stores all the cache files generated by the application; -* ``var/logs/``, stores all the log files generated by the application; -* ``var/sessions/``, stores all the session files generated by the application; -* ``tests/AppBundle/``, stores the automatic tests (e.g. Unit tests) of the - application. * ``vendor/``, this is the directory where Composer installs the application's dependencies and you should never modify any of its contents; * ``web/``, stores all the front controller files and all the web assets, such @@ -114,7 +107,8 @@ ProductBundle, then there's no advantage to having two separate bundles. Create only one bundle called AppBundle for your application logic. Implementing a single AppBundle bundle in your projects will make your code -more concise and easier to understand. +more concise and easier to understand. Starting in Symfony 2.6, the official +Symfony documentation uses the AppBundle name. .. note:: @@ -134,18 +128,13 @@ that follows these best practices: blog/ ├─ app/ + │ ├─ console + │ ├─ cache/ │ ├─ config/ + │ ├─ logs/ │ └─ Resources/ - ├─ bin/ - │ └─ console ├─ src/ │ └─ AppBundle/ - ├─ tests/ - │ └─ AppBundle/ - ├─ var/ - │ ├─ cache/ - │ ├─ logs/ - └─ sessions/ ├─ vendor/ └─ web/ ├─ app.php @@ -158,7 +147,7 @@ that follows these best practices: .. code-block:: bash - $ php bin/console generate:bundle --namespace=AppBundle --dir=src --format=annotation --no-interaction + $ php app/console generate:bundle --namespace=AppBundle --dir=src --format=annotation --no-interaction Extending the Directory Structure --------------------------------- @@ -168,6 +157,27 @@ structure of Symfony, you can :doc:`override the location of the main directories `: ``cache/``, ``logs/`` and ``web/``. +In addition, Symfony3 will use a slightly different directory structure when +it's released: + +.. code-block:: text + + blog-symfony3/ + ├─ app/ + │ ├─ config/ + │ └─ Resources/ + ├─ bin/ + │ └─ console + ├─ src/ + ├─ var/ + │ ├─ cache/ + │ └─ logs/ + ├─ vendor/ + └─ web/ + +The changes are pretty superficial, but for now, we recommend that you use +the Symfony directory structure. + .. _`Composer`: https://getcomposer.org/ .. _`Phar extension`: http://php.net/manual/en/intro.phar.php .. _`public checksums repository`: https://github.com/sensiolabs/checksums diff --git a/best_practices/forms.rst b/best_practices/forms.rst index 5c5f25b2d96..e9bf8b7cc63 100644 --- a/best_practices/forms.rst +++ b/best_practices/forms.rst @@ -21,10 +21,7 @@ form in its own PHP class:: use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\OptionsResolver\OptionsResolver; - use Symfony\Component\Form\Extension\Core\Type\TextareaType; - use Symfony\Component\Form\Extension\Core\Type\EmailType; - use Symfony\Component\Form\Extension\Core\Type\DateTimeType; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PostType extends AbstractType { @@ -32,19 +29,24 @@ form in its own PHP class:: { $builder ->add('title') - ->add('summary', TextareaType::class) - ->add('content', TextareaType::class) - ->add('authorEmail', EmailType::class) - ->add('publishedAt', DateTimeType::class) + ->add('summary', 'textarea') + ->add('content', 'textarea') + ->add('authorEmail', 'email') + ->add('publishedAt', 'datetime') ; } - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\Post' )); } + + public function getName() + { + return 'post'; + } } .. best-practice:: @@ -52,7 +54,7 @@ form in its own PHP class:: Put the form type classes in the ``AppBundle\Form`` namespace, unless you use other custom form classes like data transformers. -To use the class, use ``createForm()`` and pass the fully qualified class name:: +To use the class, use ``createForm()`` and instantiate the new class:: // ... use AppBundle\Form\PostType; @@ -61,7 +63,7 @@ To use the class, use ``createForm()`` and pass the fully qualified class name:: public function newAction(Request $request) { $post = new Post(); - $form = $this->createForm(PostType::class, $post); + $form = $this->createForm(new PostType(), $post); // ... } @@ -71,9 +73,13 @@ Registering Forms as Services You can also :ref:`register your form type as a service `. -This is only needed if your form type requires some dependencies to be injected -by the container, otherwise it is unnecessary overhead and therefore *not* -recommended to do this for all form type classes. +But this is *not* recommended unless you plan to reuse the new form type in many +places or embed it in other forms directly or via the +:doc:`collection type `. + +For most forms that are used only to edit or create something, registering +the form as a service is over-kill, and makes it more difficult to figure +out exactly which form class is being used in a controller. Form Button Configuration ------------------------- @@ -85,10 +91,9 @@ makes them easier to re-use later. Add buttons in the templates, not in the form classes or the controllers. -The Symfony Form component allows you to add buttons as fields on your form. -This is a nice way to simplify the template that renders your form. But if you -add the buttons directly in your form class, this would effectively limit the -scope of that form: +Since Symfony 2.3, you can add buttons as fields on your form. This is a nice +way to simplify the template that renders your form. But if you add the buttons +directly in your form class, this would effectively limit the scope of that form: .. code-block:: php @@ -98,7 +103,7 @@ scope of that form: { $builder // ... - ->add('save', SubmitType::class, array('label' => 'Create Post')) + ->add('save', 'submit', array('label' => 'Create Post')) ; } @@ -113,7 +118,6 @@ some developers configure form buttons in the controller:: use Symfony\Component\HttpFoundation\Request; use Symfony\Bundle\FrameworkBundle\Controller\Controller; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; use AppBundle\Entity\Post; use AppBundle\Form\PostType; @@ -124,8 +128,8 @@ some developers configure form buttons in the controller:: public function newAction(Request $request) { $post = new Post(); - $form = $this->createForm(PostType::class, $post); - $form->add('submit', SubmitType::class, array( + $form = $this->createForm(new PostType(), $post); + $form->add('submit', 'submit', array( 'label' => 'Create', 'attr' => array('class' => 'btn btn-default pull-right') )); @@ -209,3 +213,21 @@ Second, we recommend using ``$form->isSubmitted()`` in the ``if`` statement for clarity. This isn't technically needed, since ``isValid()`` first calls ``isSubmitted()``. But without this, the flow doesn't read well as it *looks* like the form is *always* processed (even on the GET request). + +Custom Form Field Types +----------------------- + +.. best-practice:: + + Add the ``app_`` prefix to your custom form field types to avoid collisions. + +Custom form field types inherit from the ``AbstractType`` class, which defines the +``getName()`` method to configure the name of that form type. These names must +be unique in the application. + +If a custom form type uses the same name as any of the Symfony's built-in form +types, it will override it. The same happens when the custom form type matches +any of the types defined by the third-party bundles installed in your application. + +Add the ``app_`` prefix to your custom form field types to avoid name collisions +that can lead to hard to debug errors. diff --git a/best_practices/i18n.rst b/best_practices/i18n.rst index 39473373df1..cfbd5fb47e2 100644 --- a/best_practices/i18n.rst +++ b/best_practices/i18n.rst @@ -32,9 +32,9 @@ Of all the available translation formats, only XLIFF and gettext have broad support in the tools used by professional translators. And since it's based on XML, you can validate XLIFF file contents as you write them. -Symfony supports notes in XLIFF files, making them more user-friendly for -translators. At the end, good translations are all about context, and these -XLIFF notes allow you to define that context. +Symfony 2.6 added support for notes inside XLIFF files, making them more +user-friendly for translators. At the end, good translations are all about +context, and these XLIFF notes allow you to define that context. .. tip:: diff --git a/best_practices/introduction.rst b/best_practices/introduction.rst index dad135249e6..2c5661c6671 100644 --- a/best_practices/introduction.rst +++ b/best_practices/introduction.rst @@ -76,8 +76,12 @@ installer and then execute this command to download the demo application: .. code-block:: bash + # Linux and Mac OS X $ symfony demo + # Windows + c:\> php symfony demo + **The demo application is a simple blog engine**, because that will allow us to focus on the Symfony concepts and features without getting buried in difficult implementation details. Instead of developing the application step by step in diff --git a/best_practices/security.rst b/best_practices/security.rst index 37f3bfd254a..1a40fdfc260 100644 --- a/best_practices/security.rst +++ b/best_practices/security.rst @@ -74,16 +74,14 @@ Authorization (i.e. Denying Access) ----------------------------------- Symfony gives you several ways to enforce authorization, including the ``access_control`` -configuration in :doc:`security.yml `, the -:ref:`@Security annotation ` and using -:ref:`isGranted ` on the ``security.authorization_checker`` +configuration in :doc:`security.yml ` and +using :ref:`isGranted ` on the ``security.context`` service directly. .. best-practice:: * For protecting broad URL patterns, use ``access_control``; - * Whenever possible, use the ``@Security`` annotation; - * Check security directly on the ``security.authorization_checker`` service whenever + * Check security directly on the ``security.context`` service whenever you have a more complex situation. There are also different ways to centralize your authorization logic, like @@ -95,132 +93,21 @@ with a custom security voter or with ACL. * For restricting access to *any* object by *any* user via an admin interface, use the Symfony ACL. -.. _best-practices-security-annotation: - -The @Security Annotation ------------------------- - -For controlling access on a controller-by-controller basis, use the ``@Security`` -annotation whenever possible. It's easy to read and is placed consistently -above each action. - -In our application, you need the ``ROLE_ADMIN`` in order to create a new post. -Using ``@Security``, this looks like: - -.. code-block:: php - - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; - // ... - - /** - * Displays a form to create a new Post entity. - * - * @Route("/new", name="admin_post_new") - * @Security("has_role('ROLE_ADMIN')") - */ - public function newAction() - { - // ... - } +.. _best-practices-directly-isGranted: +.. _checking-permissions-without-security: -Using Expressions for Complex Security Restrictions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Manually Checking Permissions +----------------------------- -If your security logic is a little bit more complex, you can use an `expression`_ -inside ``@Security``. In the following example, a user can only access the -controller if their email matches the value returned by the ``getAuthorEmail`` -method on the ``Post`` object: +If you cannot control the access based on URL patterns, you can always do +the security checks in PHP: .. code-block:: php - use AppBundle\Entity\Post; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; + use Symfony\Component\Security\Core\Exception\AccessDeniedException; - /** - * @Route("/{id}/edit", name="admin_post_edit") - * @Security("user.getEmail() == post.getAuthorEmail()") - */ - public function editAction(Post $post) - { - // ... - } - -Notice that this requires the use of the `ParamConverter`_, which automatically -queries for the ``Post`` object and puts it on the ``$post`` argument. This -is what makes it possible to use the ``post`` variable in the expression. - -This has one major drawback: an expression in an annotation cannot easily -be reused in other parts of the application. Imagine that you want to add -a link in a template that will only be seen by authors. Right now you'll -need to repeat the expression code using Twig syntax: - -.. code-block:: html+jinja - - {% if app.user and app.user.email == post.authorEmail %} - ... - {% endif %} - -The easiest solution - if your logic is simple enough - is to add a new method -to the ``Post`` entity that checks if a given user is its author: - -.. code-block:: php - - // src/AppBundle/Entity/Post.php // ... - class Post - { - // ... - - /** - * Is the given User the author of this Post? - * - * @return bool - */ - public function isAuthor(User $user = null) - { - return $user && $user->getEmail() == $this->getAuthorEmail(); - } - } - -Now you can reuse this method both in the template and in the security expression: - -.. code-block:: php - - use AppBundle\Entity\Post; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; - - /** - * @Route("/{id}/edit", name="admin_post_edit") - * @Security("post.isAuthor(user)") - */ - public function editAction(Post $post) - { - // ... - } - -.. code-block:: html+jinja - - {% if post.isAuthor(app.user) %} - ... - {% endif %} - -.. _best-practices-directly-isGranted: -.. _checking-permissions-without-security: -.. _manually-checking-permissions: - -Checking Permissions without @Security --------------------------------------- - -The above example with ``@Security`` only works because we're using the -:ref:`ParamConverter `, which gives the expression -access to the a ``post`` variable. If you don't use this, or have some other -more advanced use-case, you can always do the same security check in PHP: - -.. code-block:: php - /** * @Route("/{id}/edit", name="admin_post_edit") */ @@ -234,16 +121,7 @@ more advanced use-case, you can always do the same security check in PHP: } if (!$post->isAuthor($this->getUser())) { - $this->denyAccessUnlessGranted('edit', $post); - - // or without the shortcut: - // - // use Symfony\Component\Security\Core\Exception\AccessDeniedException; - // ... - // - // if (!$this->get('security.authorization_checker')->isGranted('edit', $post)) { - // throw $this->createAccessDeniedException(); - // } + throw new AccessDeniedException(); } // ... @@ -264,65 +142,37 @@ the same ``getAuthorEmail`` logic you used above: namespace AppBundle\Security; - use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; - use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; - use Symfony\Component\Security\Core\Authorization\Voter\Voter; + use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter; use Symfony\Component\Security\Core\User\UserInterface; - use AppBundle\Entity\Post; - class PostVoter extends Voter + // AbstractVoter class requires Symfony 2.6 or higher version + class PostVoter extends AbstractVoter { const CREATE = 'create'; const EDIT = 'edit'; - /** - * @var AccessDecisionManagerInterface - */ - private $decisionManager; - - public function __construct(AccessDecisionManagerInterface $decisionManager) + protected function getSupportedAttributes() { - $this->decisionManager = $decisionManager; + return array(self::CREATE, self::EDIT); } - protected function supports($attribute, $subject) + protected function getSupportedClasses() { - if (!in_array($attribute, array(self::CREATE, self::EDIT))) { - return false; - } - - if (!$subject instanceof Post) { - return false; - } - - return true; + return array('AppBundle\Entity\Post'); } - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + protected function isGranted($attribute, $post, $user = null) { - $user = $token->getUser(); - /** @var Post */ - $post = $subject; // $subject must be a Post instance, thanks to the supports method - if (!$user instanceof UserInterface) { return false; } - switch ($attribute) { - case self::CREATE: - // if the user is an admin, allow them to create new posts - if ($this->decisionManager->decide($token, array('ROLE_ADMIN'))) { - return true; - } - - break; - case self::EDIT: - // if the user is the author of the post, allow them to edit the posts - if ($user->getEmail() === $post->getAuthorEmail()) { - return true; - } - - break; + if ($attribute === self::CREATE && in_array('ROLE_ADMIN', $user->getRoles(), true)) { + return true; + } + + if ($attribute === self::EDIT && $user->getEmail() === $post->getAuthorEmail()) { + return true; } return false; @@ -338,46 +188,28 @@ To enable the security voter in the application, define a new service: # ... post_voter: class: AppBundle\Security\PostVoter - arguments: ['@security.access.decision_manager'] public: false tags: - { name: security.voter } -Now, you can use the voter with the ``@Security`` annotation: +Now, you can use the voter with the ``security.context`` service: .. code-block:: php - /** - * @Route("/{id}/edit", name="admin_post_edit") - * @Security("is_granted('edit', post)") - */ - public function editAction(Post $post) - { - // ... - } + use Symfony\Component\Security\Core\Exception\AccessDeniedException; -You can also use this directly with the ``security.authorization_checker`` service or -via the even easier shortcut in a controller: - -.. code-block:: php + // ... /** * @Route("/{id}/edit", name="admin_post_edit") */ public function editAction($id) { - $post = ...; // query for the post - - $this->denyAccessUnlessGranted('edit', $post); + $post = // query for the post ... - // or without the shortcut: - // - // use Symfony\Component\Security\Core\Exception\AccessDeniedException; - // ... - // - // if (!$this->get('security.authorization_checker')->isGranted('edit', $post)) { - // throw $this->createAccessDeniedException(); - // } + if (!$this->get('security.context')->isGranted('edit', $post)) { + throw new AccessDeniedException(); + } } Learn More @@ -398,7 +230,4 @@ If your company uses a user login method not supported by Symfony, you can develop :doc:`your own user provider ` and :doc:`your own authentication provider `. -.. _`ParamConverter`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html -.. _`@Security annotation`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html -.. _`expression`: http://symfony.com/doc/current/components/expression_language/introduction.html .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle diff --git a/best_practices/tests.rst b/best_practices/tests.rst index 1e9490d7aac..1f41afb9de7 100644 --- a/best_practices/tests.rst +++ b/best_practices/tests.rst @@ -28,8 +28,8 @@ functional tests, you can quickly spot any big errors before you deploy them: A functional test can be as easy as this:: - // tests/AppBundle/ApplicationAvailabilityFunctionalTest.php - namespace Tests\AppBundle; + // src/AppBundle/Tests/ApplicationAvailabilityFunctionalTest.php + namespace AppBundle\Tests; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; diff --git a/best_practices/web-assets.rst b/best_practices/web-assets.rst index f569c6df53a..a4160d62e2e 100644 --- a/best_practices/web-assets.rst +++ b/best_practices/web-assets.rst @@ -35,8 +35,6 @@ much more concise: Using Assetic ------------- -.. include:: /cookbook/assetic/_standard_edition_warning.inc - These days, you probably can't simply create static CSS and JavaScript files and include them in your template. Instead, you'll probably want to combine and minify these to improve client-side performance. You may also want to diff --git a/book/bundles.rst b/book/bundles.rst index db7994795c2..ff09cc6fc3e 100644 --- a/book/bundles.rst +++ b/book/bundles.rst @@ -107,7 +107,6 @@ Now that you've created the bundle, enable it via the ``AppKernel`` class:: { $bundles = array( // ... - // register your bundle new Acme\TestBundle\AcmeTestBundle(), ); @@ -123,7 +122,7 @@ generating a basic bundle skeleton: .. code-block:: bash - $ php bin/console generate:bundle --namespace=Acme/TestBundle + $ php app/console generate:bundle --namespace=Acme/TestBundle The bundle skeleton generates a basic controller, template and routing resource that can be customized. You'll learn more about Symfony's command-line diff --git a/book/configuration.rst b/book/configuration.rst index 073a658cda1..6562832ef09 100644 --- a/book/configuration.rst +++ b/book/configuration.rst @@ -122,13 +122,13 @@ FrameworkBundle configuration: .. code-block:: bash - $ php bin/console config:dump-reference FrameworkBundle + $ php app/console config:dump-reference FrameworkBundle The extension alias (configuration key) can also be used: .. code-block:: bash - $ php bin/console config:dump-reference framework + $ php app/console config:dump-reference framework .. note:: @@ -177,7 +177,7 @@ cached files and allow them to rebuild: .. code-block:: bash - $ php bin/console cache:clear --env=prod --no-debug + $ php app/console cache:clear --env=prod --no-debug .. note:: diff --git a/book/controller.rst b/book/controller.rst index c768b33407d..67ef1a8fbc9 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -421,26 +421,22 @@ method is just a helper method that generates the URL for a given route. Redirecting ~~~~~~~~~~~ -If you want to redirect the user to another page, use the ``redirectToRoute()`` method:: +To redirect the user's browser to another page of your app, use the ``generateUrl()`` +method in combination with another helper method called +:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::redirect` +which takes a URL as an argument:: public function indexAction() { - return $this->redirectToRoute('homepage'); - - // redirectToRoute is equivalent to using redirect() and generateUrl() together: - // return $this->redirect($this->generateUrl('homepage')); + return $this->redirect($this->generateUrl('homepage')); } -.. versionadded:: 2.6 - The ``redirectToRoute()`` method was introduced in Symfony 2.6. Previously (and still now), you - could use ``redirect()`` and ``generateUrl()`` together for this (see the example above). - -By default, the ``redirectToRoute()`` method performs a 302 (temporary) redirect. To -perform a 301 (permanent) redirect, modify the third argument:: +By default, the ``redirect()`` method performs a 302 (temporary) redirect. To +perform a 301 (permanent) redirect, modify the second argument:: public function indexAction() { - return $this->redirectToRoute('homepage', array(), 301); + return $this->redirect($this->generateUrl('homepage'), 301); } To redirect to an *external* site, use ``redirect()`` and pass it the external URL:: @@ -454,16 +450,12 @@ For more information, see the :doc:`Routing chapter `. .. tip:: - The ``redirectToRoute()`` method is simply a shortcut that creates a - ``Response`` object that specializes in redirecting the user. It's - equivalent to:: + The ``redirect()`` method is simply a shortcut that creates a ``Response`` + object that specializes in redirecting the user. It's equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; - public function indexAction() - { - return new RedirectResponse($this->generateUrl('homepage')); - } + return new RedirectResponse($this->generateUrl('homepage')); .. index:: single: Controller; Rendering templates @@ -528,12 +520,12 @@ need:: $mailer = $this->get('mailer'); -What other services exist? To list all services, use the ``debug:container`` +What other services exist? To list all services, use the ``container:debug`` console command: .. code-block:: bash - $ php bin/console debug:container + $ php app/console container:debug For more information, see the :doc:`/book/service_container` chapter. @@ -657,14 +649,12 @@ For example, imagine you're processing a form submission:: if ($form->isValid()) { // do some sort of processing - $this->addFlash( + $request->getSession()->getFlashBag()->add( 'notice', 'Your changes were saved!' ); - // $this->addFlash is equivalent to $this->get('session')->getFlashBag()->add - - return $this->redirectToRoute(...); + return $this->redirect($this->generateUrl(...)); } return $this->render(...); @@ -760,7 +750,7 @@ headers and content that's sent back to the client:: use Symfony\Component\HttpFoundation\Response; // create a simple Response with a 200 status code (the default) - $response = new Response('Hello '.$name, Response::HTTP_OK); + $response = new Response('Hello '.$name, 200); // create a JSON-response with a 200 status code $response = new Response(json_encode(array('name' => $name))); @@ -826,24 +816,24 @@ The target controller method might look something like this:: Just like when creating a controller for a route, the order of the arguments of ``fancyAction()`` doesn't matter: the matching is done by name. -.. _checking-the-validity-of-a-csrf-token: +Checking the Validity of a CSRF Token inside Controller +------------------------------------------------------- -Validating a CSRF Token ------------------------ +You may sometimes want to use :ref:`CSRF protection ` in a controller where +you don't have a Symfony form. -Sometimes, you want to use CSRF protection in an action where you don't want to -use the Symfony Form component. If, for example, you're doing a DELETE action, -you can use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::isCsrfTokenValid` +If, for example, you're doing a DELETE action, you can use the +:method:`Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\CsrfProviderInterface::isCsrfTokenValid` method to check the CSRF token:: - if ($this->isCsrfTokenValid('token_id', $submittedToken)) { - // ... do something, like deleting an object - } + $csrf = $this->container->get('form.csrf_provider'); - // isCsrfTokenValid() is equivalent to: - // $this->get('security.csrf.token_manager')->isTokenValid( - // new \Symfony\Component\Security\Csrf\CsrfToken\CsrfToken('token_id', $token) - // ); + $intention = 'authenticate'; + $token = $csrf->generateCsrfToken($intention); + + if (!$csrf->isCsrfTokenValid($intention, $token)) { + // CSRF token invalid! Do something, like redirect with an error. + } Final Thoughts -------------- diff --git a/book/doctrine.rst b/book/doctrine.rst index cdb6025adc5..6287f49ecdb 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -116,7 +116,7 @@ can automatically generate an empty ``test_project`` database for you: .. code-block:: bash - $ php bin/console doctrine:database:create + $ php app/console doctrine:database:create .. sidebar:: Setting up the Database to be UTF8 @@ -128,8 +128,12 @@ can automatically generate an empty ``test_project`` database for you: .. code-block:: bash - $ php bin/console doctrine:database:drop --force - $ php bin/console doctrine:database:create + $ php app/console doctrine:database:drop --force + $ php app/console doctrine:database:create + + There's no way to configure these defaults inside Doctrine, as it tries to be + as agnostic as possible in terms of environment configuration. One way to solve + this problem is to configure server-level defaults. Setting UTF8 defaults for MySQL is as simple as adding a few lines to your configuration file (typically ``my.cnf``): @@ -141,55 +145,6 @@ can automatically generate an empty ``test_project`` database for you: collation-server = utf8mb4_general_ci # Replaces utf8_general_ci character-set-server = utf8mb4 # Replaces utf8 - You can also change the defaults for Doctrine so that the generated SQL - uses the correct character set. - - .. configuration-block:: - - .. code-block:: yaml - - # app/config/config.yml - doctrine: - dbal: - charset: utf8mb4 - default_table_options: - charset: utf8mb4 - collate: utf8mb4_unicode_ci - - .. code-block:: xml - - - - - - - - utf8mb4 - utf8mb4_unicode_ci - - - - - .. code-block:: php - - // app/config/config.php - $configuration->loadFromExtension('doctrine', array( - 'dbal' => array( - 'charset' => 'utf8mb4', - 'default_table_options' => array( - 'charset' => 'utf8mb4' - 'collate' => 'utf8mb4_unicode_ci' - ) - ), - )); - We recommend against MySQL's ``utf8`` character set, since it does not support 4-byte unicode characters, and strings containing them will be truncated. This is fixed by the `newer utf8mb4 character set`_. @@ -272,7 +227,7 @@ just a simple PHP class. .. code-block:: bash - $ php bin/console doctrine:generate:entity + $ php app/console doctrine:generate:entity .. index:: single: Doctrine; Adding mapping metadata @@ -441,7 +396,7 @@ the following command can generate these boilerplate methods automatically: .. code-block:: bash - $ php bin/console doctrine:generate:entities AppBundle/Entity/Product + $ php app/console doctrine:generate:entities AppBundle/Entity/Product This command makes sure that all the getters and setters are generated for the ``Product`` class. This is a safe command - you can run it over and @@ -482,10 +437,10 @@ mapping information) of a bundle or an entire namespace: .. code-block:: bash # generates all entities in the AppBundle - $ php bin/console doctrine:generate:entities AppBundle + $ php app/console doctrine:generate:entities AppBundle # generates all entities of bundles in the Acme namespace - $ php bin/console doctrine:generate:entities Acme + $ php app/console doctrine:generate:entities Acme .. _book-doctrine-creating-the-database-tables-schema: @@ -500,7 +455,7 @@ in your application. To do this, run: .. code-block:: bash - $ php bin/console doctrine:schema:update --force + $ php app/console doctrine:schema:update --force .. tip:: @@ -723,7 +678,7 @@ you have a route that maps a product id to an update action in a controller:: $product->setName('New product name!'); $em->flush(); - return $this->redirectToRoute('homepage'); + return $this->redirect($this->generateUrl('homepage')); } Updating an object involves just three steps: @@ -897,7 +852,7 @@ used earlier to generate the missing getter and setter methods: .. code-block:: bash - $ php bin/console doctrine:generate:entities AppBundle + $ php app/console doctrine:generate:entities AppBundle Next, add a new method - ``findAllOrderedByName()`` - to the newly generated repository class. This method will query for all the ``Product`` entities, @@ -951,7 +906,7 @@ you can let Doctrine create the class for you. .. code-block:: bash - $ php bin/console doctrine:generate:entity --no-interaction \ + $ php app/console doctrine:generate:entity --no-interaction \ --entity="AppBundle:Category" \ --fields="name:string(255)" @@ -1108,7 +1063,7 @@ methods for you: .. code-block:: bash - $ php bin/console doctrine:generate:entities AppBundle + $ php app/console doctrine:generate:entities AppBundle Ignore the Doctrine metadata for a moment. You now have two classes - ``Category`` and ``Product`` with a natural one-to-many relationship. The ``Category`` @@ -1137,7 +1092,7 @@ table, and ``product.category_id`` column, and new foreign key: .. code-block:: bash - $ php bin/console doctrine:schema:update --force + $ php app/console doctrine:schema:update --force .. note:: @@ -1252,8 +1207,7 @@ to the given ``Category`` object via their ``category_id`` value. $category = $product->getCategory(); // prints "Proxies\AppBundleEntityCategoryProxy" - dump(get_class($category)); - die(); + var_dump(get_class($category)); This proxy object extends the true ``Category`` object, and looks and acts exactly like it. The difference is that, by using a proxy object, diff --git a/book/forms.rst b/book/forms.rst index 0fde7985056..f0b4a2945eb 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -80,9 +80,6 @@ from inside a controller:: use AppBundle\Entity\Task; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; class DefaultController extends Controller { @@ -94,9 +91,9 @@ from inside a controller:: $task->setDueDate(new \DateTime('tomorrow')); $form = $this->createFormBuilder($task) - ->add('task', TextType::class) - ->add('dueDate', DateType::class) - ->add('save', SubmitType::class, array('label' => 'Create Task')) + ->add('task', 'text') + ->add('dueDate', 'date') + ->add('save', 'submit', array('label' => 'Create Task')) ->getForm(); return $this->render('default/new.html.twig', array( @@ -119,13 +116,16 @@ building the form. In this example, you've added two fields to your form - ``task`` and ``dueDate`` - corresponding to the ``task`` and ``dueDate`` properties of the ``Task`` class. -You've also assigned each a "type" (e.g. ``TextType`` and ``DateType``), -represented by its fully qualified class name. Among other things, it determines -which HTML form tag(s) is rendered for that field. +You've also assigned each a "type" (e.g. ``text``, ``date``), which, among +other things, determines which HTML form tag(s) is rendered for that field. Finally, you added a submit button with a custom label for submitting the form to the server. +.. versionadded:: 2.3 + Support for submit buttons was introduced in Symfony 2.3. Before that, you had + to add buttons to the form's HTML manually. + Symfony comes with many built-in types that will be discussed shortly (see :ref:`book-forms-type-reference`). @@ -224,9 +224,9 @@ your controller:: $task = new Task(); $form = $this->createFormBuilder($task) - ->add('task', TextType::class) - ->add('dueDate', DateType::class) - ->add('save', SubmitType::class, array('label' => 'Create Task')) + ->add('task', 'text') + ->add('dueDate', 'date') + ->add('save', 'submit', array('label' => 'Create Task')) ->getForm(); $form->handleRequest($request); @@ -234,20 +234,26 @@ your controller:: if ($form->isSubmitted() && $form->isValid()) { // ... perform some action, such as saving the task to the database - return $this->redirectToRoute('task_success'); + return $this->redirect($this->generateUrl('task_success')); } return $this->render('default/new.html.twig', array( 'form' => $form->createView(), )); } - + .. caution:: Be aware that the ``createView()`` method should be called *after* ``handleRequest`` is called. Otherwise, changes done in the ``*_SUBMIT`` events aren't applied to the view (like validation errors). +.. versionadded:: 2.3 + The :method:`Symfony\\Component\\Form\\FormInterface::handleRequest` method + was introduced in Symfony 2.3. Previously, the ``$request`` was passed + to the ``submit`` method - a strategy which is deprecated and will be + removed in Symfony 3.0. For details on that method, see :ref:`cookbook-form-submit-request`. + This controller follows a common pattern for handling forms, and has three possible paths: @@ -290,15 +296,18 @@ possible paths: Submitting Forms with Multiple Buttons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + Support for buttons in forms was introduced in Symfony 2.3. + When your form contains more than one submit button, you will want to check which of the buttons was clicked to adapt the program flow in your controller. To do this, add a second button with the caption "Save and add" to your form:: $form = $this->createFormBuilder($task) - ->add('task', TextType::class) - ->add('dueDate', DateType::class) - ->add('save', SubmitType::class, array('label' => 'Create Task')) - ->add('saveAndAdd', SubmitType::class, array('label' => 'Save and Add')) + ->add('task', 'text') + ->add('dueDate', 'date') + ->add('save', 'submit', array('label' => 'Create Task')) + ->add('saveAndAdd', 'submit', array('label' => 'Save and Add')) ->getForm(); In your controller, use the button's @@ -312,7 +321,7 @@ querying if the "Save and add" button was clicked:: ? 'task_new' : 'task_success'; - return $this->redirectToRoute($nextAction); + return $this->redirect($this->generateUrl($nextAction)); } .. index:: @@ -466,12 +475,12 @@ you'll need to specify which validation group(s) your form should use:: ))->add(...); If you're creating :ref:`form classes ` (a -good practice), then you'll need to add the following to the ``configureOptions()`` +good practice), then you'll need to add the following to the ``setDefaultOptions()`` method:: - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => array('registration'), @@ -487,12 +496,15 @@ be used to validate the underlying object. Disabling Validation ~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + The ability to set ``validation_groups`` to false was introduced in Symfony 2.3. + Sometimes it is useful to suppress the validation of a form altogether. For these cases you can set the ``validation_groups`` option to ``false``:: - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => false, @@ -516,10 +528,10 @@ If you need some advanced logic to determine the validation groups (e.g. based on submitted data), you can set the ``validation_groups`` option to an array callback:: - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; // ... - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => array( @@ -536,10 +548,10 @@ You can also define whole logic inline by using a ``Closure``:: use AppBundle\Entity\Client; use Symfony\Component\Form\FormInterface; - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; // ... - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => function (FormInterface $form) { @@ -560,10 +572,10 @@ of the entity as well you have to adjust the option as follows:: use AppBundle\Entity\Client; use Symfony\Component\Form\FormInterface; - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; // ... - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => function (FormInterface $form) { @@ -587,6 +599,9 @@ work in the book section about :ref:`validation groups createFormBuilder($task) // ... - ->add('nextStep', SubmitType::class) - ->add('previousStep', SubmitType::class) + ->add('nextStep', 'submit') + ->add('previousStep', 'submit') ->getForm(); Then, we configure the button for returning to the previous step to run @@ -607,7 +622,7 @@ so we set its ``validation_groups`` option to false:: $form = $this->createFormBuilder($task) // ... - ->add('previousStep', SubmitType::class, array( + ->add('previousStep', 'submit', array( 'validation_groups' => false, )) ->getForm(); @@ -640,11 +655,11 @@ Field Type Options Each field type has a number of options that can be used to configure it. For example, the ``dueDate`` field is currently being rendered as 3 select -boxes. However, the :doc:`DateType ` can be +boxes. However, the :doc:`date field ` can be configured to be rendered as a single text box (where the user would enter the date as a string in the box):: - ->add('dueDate', DateType::class, array('widget' => 'single_text')) + ->add('dueDate', 'date', array('widget' => 'single_text')) .. image:: /images/book/form-simple2.png :align: center @@ -662,7 +677,7 @@ the documentation for each type. :ref:`disable HTML5 validation ` or set the ``required`` option on your field to ``false``:: - ->add('dueDate', DateType::class, array( + ->add('dueDate', 'date', array( 'widget' => 'single_text', 'required' => false )) @@ -681,7 +696,7 @@ the documentation for each type. The label for the form field can be set using the ``label`` option, which can be applied to any field:: - ->add('dueDate', DateType::class, array( + ->add('dueDate', 'date', array( 'widget' => 'single_text', 'label' => 'Due Date', )) @@ -702,7 +717,7 @@ Now that you've added validation metadata to the ``Task`` class, Symfony already knows a bit about your fields. If you allow it, Symfony can "guess" the type of your field and set it up for you. In this example, Symfony can guess from the validation rules that both the ``task`` field is a normal -``TextType`` field and the ``dueDate`` field is a ``DateType`` field:: +``text`` field and the ``dueDate`` field is a ``date`` field:: public function newAction() { @@ -711,7 +726,7 @@ guess from the validation rules that both the ``task`` field is a normal $form = $this->createFormBuilder($task) ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) - ->add('save', SubmitType::class) + ->add('save', 'submit') ->getForm(); } @@ -763,7 +778,7 @@ the correct values of a number of field options. If you'd like to change one of the guessed values, you can override it by passing the option in the options field array:: - ->add('task', null, array('attr' => array('maxlength' => 4))) + ->add('task', null, array('max_length' => 4)) .. index:: single: Forms; Rendering in a template @@ -972,9 +987,9 @@ ways. If you build your form in the controller, you can use ``setAction()`` and $form = $this->createFormBuilder($task) ->setAction($this->generateUrl('target_route')) ->setMethod('GET') - ->add('task', TextType::class) - ->add('dueDate', DateType::class) - ->add('save', SubmitType::class) + ->add('task', 'text') + ->add('dueDate', 'date') + ->add('save', 'submit') ->getForm(); .. note:: @@ -986,10 +1001,7 @@ In :ref:`book-form-creating-form-classes` you will learn how to move the form building code into separate classes. When using an external form class in the controller, you can pass the action and method as form options:: - use AppBundle\Form\Type\TaskType; - // ... - - $form = $this->createForm(TaskType::class, $task, array( + $form = $this->createForm(new TaskType(), $task, array( 'action' => $this->generateUrl('target_route'), 'method' => 'GET', )); @@ -1008,7 +1020,7 @@ to the ``form()`` or the ``form_start()`` helper: start($form, array( - 'action' => $view['router']->path('target_route'), + 'action' => $view['router']->generate('target_route'), 'method' => 'GET', )) ?> @@ -1039,7 +1051,6 @@ that will house the logic for building the task form:: use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; class TaskType extends AbstractType { @@ -1048,21 +1059,36 @@ that will house the logic for building the task form:: $builder ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) - ->add('save', SubmitType::class) + ->add('save', 'submit') ; } + + public function getName() + { + return 'app_task'; + } } +.. caution:: + + The ``getName()`` method returns the identifier of this form "type". These + identifiers must be unique in the application. Unless you want to override + a built-in type, they should be different from the default Symfony types + and from any type defined by a third-party bundle installed in your application. + Consider prefixing your types with ``app_`` to avoid identifier collisions. + This new class contains all the directions needed to create the task form. It can be used to quickly build a form object in the controller:: // src/AppBundle/Controller/DefaultController.php + + // add this new use statement at the top of the class use AppBundle\Form\Type\TaskType; public function newAction() { $task = ...; - $form = $this->createForm(TaskType::class, $task); + $form = $this->createForm(new TaskType(), $task); // ... } @@ -1083,9 +1109,9 @@ the choice is ultimately up to you. good idea to explicitly specify the ``data_class`` option by adding the following to your form type class:: - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\Task', @@ -1109,7 +1135,7 @@ the choice is ultimately up to you. $builder ->add('task') ->add('dueDate', null, array('mapped' => false)) - ->add('save', SubmitType::class) + ->add('save', 'submit') ; } @@ -1129,8 +1155,8 @@ the choice is ultimately up to you. Defining your Forms as Services ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Your form type might have some external dependencies. You can define your form -type as a service, and inject all dependencies you need. +Defining your form type as a service is a good practice and makes it really +easy to use in your application. .. note:: @@ -1138,39 +1164,6 @@ type as a service, and inject all dependencies you need. :doc:`later on in this book `. Things will be more clear after reading that chapter. -You might want to use a service defined as ``app.my_service`` in your form -type. Create a constructor to your form type to receive the service:: - - // src/AppBundle/Form/Type/TaskType.php - namespace AppBundle\Form\Type; - - use App\Utility\MyService; - use Symfony\Component\Form\AbstractType; - use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\Form\Extension\Core\Type\SubmitType; - - class TaskType extends AbstractType - { - private $myService; - - public function __construct(MyService $myService) - { - $this->myService = $myService; - } - - public function buildForm(FormBuilderInterface $builder, array $options) - { - // You can now use myService. - $builder - ->add('task') - ->add('dueDate', null, array('widget' => 'single_text')) - ->add('save', SubmitType::class) - ; - } - } - -Define your form type as a service. - .. configuration-block:: .. code-block:: yaml @@ -1179,9 +1172,8 @@ Define your form type as a service. services: app.form.type.task: class: AppBundle\Form\Type\TaskType - arguments: ["@app.my_service"] tags: - - { name: form.type } + - { name: form.type, alias: app_task } .. code-block:: xml @@ -1193,8 +1185,7 @@ Define your form type as a service. - - + @@ -1202,11 +1193,43 @@ Define your form type as a service. .. code-block:: php // src/AppBundle/Resources/config/services.php - use Symfony\Component\DependencyInjection\Reference; + $container + ->register( + 'app.form.type.task', + 'AppBundle\Form\Type\TaskType' + ) + ->addTag('form.type', array( + 'alias' => 'app_task', + )) + ; + +That's it! Now you can use your form type directly in a controller:: + + // src/AppBundle/Controller/DefaultController.php + // ... + + public function newAction() + { + $task = ...; + $form = $this->createForm('task', $task); + + // ... + } + +or even use from within the form type of another form:: + + // src/AppBundle/Form/Type/ListType.php + // ... + + class ListType extends AbstractType + { + public function buildForm(FormBuilderInterface $builder, array $options) + { + // ... - $container->register('app.form.type.task', 'AppBundle\Form\Type\TaskType') - ->addArgument(new Reference('app.my_service')) - ->addTag('form.type') + $builder->add('someTask', 'task'); + } + } Read :ref:`form-cookbook-form-field-service` for more information. @@ -1229,7 +1252,7 @@ it after a form submission can be done when the form is valid:: $em->persist($task); $em->flush(); - return $this->redirectToRoute('task_success'); + return $this->redirect($this->generateUrl('task_success')); } If, for some reason, you don't have access to your original ``$task`` object, @@ -1317,7 +1340,7 @@ create a form class so that a ``Category`` object can be modified by the user:: use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CategoryType extends AbstractType { @@ -1326,12 +1349,17 @@ create a form class so that a ``Category`` object can be modified by the user:: $builder->add('name'); } - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\Category', )); } + + public function getName() + { + return 'category'; + } } The end goal is to allow the ``Category`` of a ``Task`` to be modified right @@ -1342,13 +1370,12 @@ class: .. code-block:: php use Symfony\Component\Form\FormBuilderInterface; - use AppBundle\Form\Type\CategoryType; public function buildForm(FormBuilderInterface $builder, array $options) { // ... - $builder->add('category', CategoryType::class); + $builder->add('category', new CategoryType()); } The fields from ``CategoryType`` can now be rendered alongside those from @@ -1395,7 +1422,7 @@ form with many ``Product`` sub-forms). This is done by using the ``collection`` field type. For more information see the ":doc:`/cookbook/form/form_collections`" cookbook -entry and the :doc:`CollectionType ` reference. +entry and the :doc:`collection ` field type reference. .. index:: single: Forms; Theming @@ -1462,7 +1489,7 @@ renders the form: {% form_theme form 'form/fields.html.twig' %} {# or if you want to use multiple themes #} - {% form_theme form 'form/fields.html.twig' 'form/fields2.html.twig' %} + {% form_theme form 'form/fields.html.twig' 'Form/fields2.html.twig' %} {# ... render the form #} @@ -1602,8 +1629,9 @@ file: # app/config/config.yml twig: - form_themes: - - 'form/fields.html.twig' + form: + resources: + - 'form/fields.html.twig' # ... .. code-block:: xml @@ -1617,7 +1645,9 @@ file: http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd"> - form/fields.html.twig + + form/fields.html.twig + @@ -1626,8 +1656,10 @@ file: // app/config/config.php $container->loadFromExtension('twig', array( - 'form_themes' => array( - 'form/fields.html.twig', + 'form' => array( + 'resources' => array( + 'form/fields.html.twig', + ), ), // ... )); @@ -1759,20 +1791,20 @@ that all un-rendered fields are output. The CSRF token can be customized on a form-by-form basis. For example:: - use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TaskType extends AbstractType { // ... - public function configureOptions(OptionsResolver $resolver) + public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\Task', 'csrf_protection' => true, 'csrf_field_name' => '_token', // a unique key to help generate the secret token - 'csrf_token_id' => 'task_item', + 'intention' => 'task_item', )); } @@ -1788,8 +1820,8 @@ section. .. note:: - The ``csrf_token_id`` option is optional but greatly enhances the security - of the generated token by making it different for each form. + The ``intention`` option is optional but greatly enhances the security of + the generated token by making it different for each form. .. caution:: @@ -1819,10 +1851,10 @@ an array of the submitted data. This is actually really easy:: { $defaultData = array('message' => 'Type your message here'); $form = $this->createFormBuilder($defaultData) - ->add('name', TextType::class) - ->add('email', EmailType::class) - ->add('message', TextareaType::class) - ->add('send', SubmitType::class) + ->add('name', 'text') + ->add('email', 'email') + ->add('message', 'textarea') + ->add('send', 'submit') ->getForm(); $form->handleRequest($request); @@ -1879,17 +1911,21 @@ The answer is to setup the constraints yourself, and attach them to the individu fields. The overall approach is covered a bit more in the :ref:`validation chapter `, but here's a short example: +.. versionadded:: 2.1 + The ``constraints`` option, which accepts a single constraint or an array + of constraints (before 2.1, the option was called ``validation_constraint``, + and only accepted a single constraint) was introduced in Symfony 2.1. + .. code-block:: php use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; - use Symfony\Component\Form\Extension\Core\Type\TextType; $builder - ->add('firstName', TextType::class, array( + ->add('firstName', 'text', array( 'constraints' => new Length(array('min' => 3)), )) - ->add('lastName', TextType::class, array( + ->add('lastName', 'text', array( 'constraints' => array( new NotBlank(), new Length(array('min' => 3)), @@ -1929,7 +1965,7 @@ Learn more from the Cookbook ---------------------------- * :doc:`/cookbook/doctrine/file_uploads` -* :doc:`FileType Reference ` +* :doc:`File Field Reference ` * :doc:`Creating Custom Field Types ` * :doc:`/cookbook/form/form_customization` * :doc:`/cookbook/form/dynamic_form_modification` @@ -1939,7 +1975,7 @@ Learn more from the Cookbook .. _`Symfony Form component`: https://github.com/symfony/form .. _`DateTime`: http://php.net/manual/en/class.datetime.php -.. _`Twig Bridge`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/Twig -.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig -.. _`Cross-site request forgery`: http://en.wikipedia.org/wiki/Cross-site_request_forgery -.. _`view on GitHub`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form +.. _`Twig Bridge`: https://github.com/symfony/symfony/tree/2.3/src/Symfony/Bridge/Twig +.. _`form_div_layout.html.twig`: https://github.com/symfony/symfony/blob/2.3/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +.. _`Cross-site request forgery`: https://en.wikipedia.org/wiki/Cross-site_request_forgery +.. _`view on GitHub`: https://github.com/symfony/symfony/tree/2.3/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index 6c87f84e4f4..63243ef3a23 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -417,7 +417,7 @@ content: { "require": { - "symfony/symfony": "3.0.*" + "symfony/symfony": "2.3.*" }, "autoload": { "files": ["model.php","controllers.php"] @@ -457,7 +457,7 @@ the HTTP response being returned. Use them to improve the blog:: $response = show_action($request->query->get('id')); } else { $html = '

Page Not Found

'; - $response = new Response($html, Response::HTTP_NOT_FOUND); + $response = new Response($html, 404); } // echo the headers and send the response @@ -573,7 +573,7 @@ database and the Templating component to render a template and return a
  • - generate( 'blog_show', array('id' => $post->getId()) ) ?>"> diff --git a/book/http_cache.rst b/book/http_cache.rst index 76879a288a6..2e3d803fa2a 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -145,9 +145,12 @@ To enable caching, modify the code of a front controller to use the caching kernel:: // web/app.php + require_once __DIR__.'/../app/bootstrap.php.cache'; + require_once __DIR__.'/../app/AppKernel.php'; + require_once __DIR__.'/../app/AppCache.php'; + use Symfony\Component\HttpFoundation\Request; - // ... $kernel = new AppKernel('prod', false); $kernel->loadClassCache(); // wrap the default AppKernel with the AppCache one @@ -909,7 +912,7 @@ Here is how you can configure the Symfony reverse proxy to support the if ('127.0.0.1' !== $request->getClientIp()) { return new Response( 'Invalid HTTP method', - Response::HTTP_BAD_REQUEST + 400 ); } @@ -1084,18 +1087,24 @@ matter), Symfony uses the standard ``render`` helper to configure ESI tags: - + // you can use a controller reference + use Symfony\Component\HttpKernel\Controller\ControllerReference; render( - new \Symfony\Component\HttpKernel\Controller\ControllerReference( + new ControllerReference( 'AppBundle:News:latest', array('maxPerPage' => 5) ), array('strategy' => 'esi') ) ?> - + // ... or a URL + use Symfony\Component\Routing\Generator\UrlGeneratorInterface; render( - $view['router']->url('latest_news', array('maxPerPage' => 5)), + $view['router']->generate( + 'latest_news', + array('maxPerPage' => 5), + UrlGeneratorInterface::ABSOLUTE_URL + ), array('strategy' => 'esi'), ) ?> diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 97c9e346323..8f8da7213cc 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -282,7 +282,7 @@ interface to construct the response that needs to be returned to the client:: $response = new Response(); $response->setContent('

    Hello world!

    '); - $response->setStatusCode(Response::HTTP_OK); + $response->setStatusCode(200); $response->headers->set('Content-Type', 'text/html'); // prints the HTTP headers followed by the content @@ -377,7 +377,7 @@ on that value. This can get ugly quickly:: } elseif ('/contact' === $path) { $response = new Response('Contact us'); } else { - $response = new Response('Page not found.', Response::HTTP_NOT_FOUND); + $response = new Response('Page not found.', 404); } $response->send(); diff --git a/book/includes/_service_container_my_mailer.rst.inc b/book/includes/_service_container_my_mailer.rst.inc deleted file mode 100644 index f14c2fbe282..00000000000 --- a/book/includes/_service_container_my_mailer.rst.inc +++ /dev/null @@ -1,35 +0,0 @@ -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - app.mailer: - class: AppBundle\Mailer - arguments: [sendmail] - - .. code-block:: xml - - - - - - - - sendmail - - - - - .. code-block:: php - - // app/config/services.php - use Symfony\Component\DependencyInjection\Definition; - - $container->setDefinition('app.mailer', new Definition( - 'AppBundle\Mailer', - array('sendmail') - )); diff --git a/book/installation.rst b/book/installation.rst index 7adbdc415fc..cf7fb16d12f 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -4,16 +4,9 @@ Installing and Configuring Symfony ================================== -Welcome to Symfony! Starting a new Symfony project is easy. In fact, you'll have -your first working Symfony application up and running in just a few short minutes. - -.. seealso:: - - Do you prefer video tutorials? Check out the `Joyful Development with Symfony`_ - screencast series from KnpUniversity. - -To make creating new applications even simpler, Symfony provides an installer. -Downloading it is your first step. +The goal of this chapter is to get you up and running with a working application +built on top of Symfony. In order to simplify the process of creating new +applications, Symfony provides an installer application. Installing the Symfony Installer -------------------------------- @@ -61,8 +54,6 @@ execute it as follows: c:\> move symfony c:\projects c:\projects\> php symfony -.. _installation-creating-the-app: - Creating the Symfony Application -------------------------------- @@ -104,15 +95,16 @@ optional second argument of the ``new`` command: .. code-block:: bash # use the most recent version in any Symfony branch - $ symfony new my_project_name 2.8 - $ symfony new my_project_name 3.0 + $ symfony new my_project_name 2.3 + $ symfony new my_project_name 2.5 + $ symfony new my_project_name 2.6 # use a specific Symfony version - $ symfony new my_project_name 2.7.3 - $ symfony new my_project_name 2.8.1 + $ symfony new my_project_name 2.3.26 + $ symfony new my_project_name 2.6.5 # use a beta or RC version (useful for testing new Symfony versions) - $ symfony new my_project 3.0.0-BETA1 + $ symfony new my_project 2.7.0-BETA1 $ symfony new my_project 2.7.0-RC1 The installer also supports a special version called ``lts`` which installs the @@ -159,7 +151,7 @@ version as the second argument of the ``create-project`` command: .. code-block:: bash - $ composer create-project symfony/framework-standard-edition my_project_name "3.0.*" + $ composer create-project symfony/framework-standard-edition my_project_name "2.3.*" .. tip:: @@ -177,7 +169,7 @@ browsing the project directory and executing this command: .. code-block:: bash $ cd my_project_name/ - $ php bin/console server:run + $ php app/console server:run Then, open your browser and access the ``http://localhost:8000/`` URL to see the Welcome Page of Symfony: @@ -223,10 +215,10 @@ If there are any issues, correct them now before moving on. .. sidebar:: Setting up Permissions - One common issue when installing Symfony is that the ``var`` directory must - be writable both by the web server and the command line user. On a UNIX - system, if your web server user is different from your command line user - who owns the files, you can try one of the following solutions. + One common issue when installing Symfony is that the ``app/cache`` and + ``app/logs`` directories must be writable both by the web server and the + command line user. On a UNIX system, if your web server user is different + from your command line user, you can try one of the following solutions. **1. Use the same user for the CLI and the web server** @@ -245,11 +237,12 @@ If there are any issues, correct them now before moving on. .. code-block:: bash - $ rm -rf var/cache/* var/logs/* var/sessions/* + $ rm -rf app/cache/* + $ rm -rf app/logs/* $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` - $ sudo chmod -R +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" var - $ sudo chmod -R +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" var + $ sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs + $ sudo chmod +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs **3. Using ACL on a system that does not support chmod +a** @@ -263,8 +256,8 @@ If there are any issues, correct them now before moving on. .. code-block:: bash $ HTTPDUSER=`ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1` - $ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX var - $ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX var + $ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs + $ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/cache app/logs If this doesn't work, try adding ``-n`` option. @@ -273,7 +266,7 @@ If there are any issues, correct them now before moving on. If none of the previous methods work for you, change the umask so that the cache and log directories will be group-writable or world-writable (depending if the web server user and the command line user are in the same group or not). - To achieve this, put the following line at the beginning of the ``bin/console``, + To achieve this, put the following line at the beginning of the ``app/console``, ``web/app.php`` and ``web/app_dev.php`` files:: umask(0002); // This will let the permissions be 0775 @@ -307,18 +300,6 @@ them all at once: Depending on the complexity of your project, this update process can take up to several minutes to complete. -.. tip:: - - Symfony provides a command to check whether your project's dependencies - contain any known security vulnerability: - - .. code-block:: bash - - $ php bin/console security:check - - A good security practice is to execute this command regularly to be able to - update or replace compromised dependencies as soon as possible. - Installing the Symfony Demo Application --------------------------------------- @@ -339,7 +320,7 @@ of the Symfony Installer anywhere in your system: c:\projects\> php symfony demo Once downloaded, enter into the ``symfony_demo/`` directory and run the PHP's -built-in web server executing the ``php bin/console server:run`` command. Access +built-in web server executing the ``php app/console server:run`` command. Access to the ``http://localhost:8000`` URL in your browser to start using the Symfony Demo application. @@ -414,7 +395,6 @@ need in your new application. Be sure to also check out the :doc:`Cookbook `, which contains a wide variety of articles about solving specific problems with Symfony. -.. _`Joyful Development with Symfony`: http://knpuniversity.com/screencast/symfony .. _`explained in this post`: http://fabien.potencier.org/signing-project-releases.html .. _`Composer`: https://getcomposer.org/ .. _`Composer download page`: https://getcomposer.org/download/ diff --git a/book/page_creation.rst b/book/page_creation.rst index cc32869e341..ce3be3ce65b 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -21,11 +21,6 @@ simple two-step process: Just like on the web, every interaction is initiated by an HTTP request. Your job is pure and simple: understand that request and return a response. -.. seealso:: - - Do you prefer video tutorials? Check out the `Joyful Development with Symfony`_ - screencast series from KnpUniversity. - .. index:: single: Page creation; Example @@ -97,8 +92,8 @@ Suppose you want to create a JSON endpoint that returns the lucky number. Just add a second method to ``LuckyController``:: // src/AppBundle/Controller/LuckyController.php - // ... + class LuckyController { // ... @@ -127,8 +122,8 @@ Try this out in your browser: You can even shorten this with the handy :class:`Symfony\\Component\\HttpFoundation\\JsonResponse`:: // src/AppBundle/Controller/LuckyController.php - // ... + // --> don't forget this new use statement use Symfony\Component\HttpFoundation\JsonResponse; @@ -163,8 +158,8 @@ at the end: .. code-block:: php-annotations // src/AppBundle/Controller/LuckyController.php - // ... + class LuckyController { /** @@ -269,8 +264,8 @@ to use Twig - or many other tools in Symfony - is to extend Symfony's base :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class:: // src/AppBundle/Controller/LuckyController.php - // ... + // --> add this new use statement use Symfony\Bundle\FrameworkBundle\Controller\Controller; @@ -291,8 +286,8 @@ Twig templates, another that can log messages and many more. To render a Twig template, use a service called ``templating``:: // src/AppBundle/Controller/LuckyController.php - // ... + class LuckyController extends Controller { /** @@ -324,8 +319,8 @@ But this can get even easier! By extending the ``Controller`` class, you also get a lot of shortcut methods, like ``render()``:: // src/AppBundle/Controller/LuckyController.php - // ... + /** * @Route("/lucky/number/{count}") */ @@ -429,41 +424,30 @@ worked inside the two most important directories: else). As you get more advanced, you'll learn what can be done inside each of these. -The ``app/`` directory also holds some other things, like ``app/AppKernel.php``, -which you'll use to enable new bundles (this is one of a *very* short list of +The ``app/`` directory also holds a few other things, like the cache directory +``app/cache/``, the logs directory ``app/logs/`` and ``app/AppKernel.php``, +which you'll use to enable new bundles (and one of a *very* short list of PHP files in ``app/``). The ``src/`` directory has just one directory - ``src/AppBundle`` - and everything lives inside of it. A bundle is like a "plugin" and you can `find open source bundles`_ and install them into your project. But even -*your* code lives in a bundle - typically *AppBundle* (though there's -nothing special about AppBundle). To find out more about bundles and +*your* code lives in a bundle - typically ``AppBundle`` (though there's +nothing special about ``AppBundle``). To find out more about bundles and why you might create multiple bundles (hint: sharing code between projects), see the :doc:`Bundles ` chapter. So what about the other directories in the project? +``vendor/`` + Vendor (i.e. third-party) libraries and bundles are downloaded here by + the `Composer`_ package manager. + ``web/`` This is the document root for the project and contains any publicly accessible files, like CSS, images and the Symfony front controllers that execute the app (``app_dev.php`` and ``app.php``). -``tests/`` - The automatic tests (e.g. Unit tests) of your application live here. - -``bin/`` - The "binary" files live here. The most important one is the ``console`` - file which is used to execute Symfony commands via the console. - -``var/`` - This is where automatically created files are stored, like cache files - (``var/cache/``) and logs (``var/logs/``). - -``vendor/`` - Third-party libraries, packages and bundles are downloaded here by - the `Composer`_ package manager. You should never edit something in this - directory. - .. seealso:: Symfony is flexible. If you need to, you can easily override the default @@ -481,8 +465,8 @@ is ``app/config/config.yml``: .. code-block:: yaml # app/config/config.yml - # ... + framework: secret: '%secret%' router: @@ -550,11 +534,11 @@ by changing one option in this configuration file. To find out how, see the :doc:`Configuration Reference ` section. Or, to get a big example dump of all of the valid configuration under a key, -use the handy ``bin/console`` command: +use the handy ``app/console`` command: .. code-block:: bash - $ php bin/console config:dump-reference framework + $ app/console config:dump-reference framework There's a lot more power behind Symfony's configuration system, including environments, imports and parameters. To learn all of it, see the @@ -581,7 +565,6 @@ There's also a :doc:`Cookbook ` *packed* with more advanced Have fun! -.. _`Joyful Development with Symfony`: http://knpuniversity.com/screencast/symfony/first-page -.. _`app/Resources/views/base.html.twig`: https://github.com/symfony/symfony-standard/blob/3.0/app/Resources/views/base.html.twig +.. _`app/Resources/views/base.html.twig`: https://github.com/symfony/symfony-standard/blob/2.7/app/Resources/views/base.html.twig .. _`Composer`: https://getcomposer.org .. _`find open source bundles`: http://knpbundles.com diff --git a/book/performance.rst b/book/performance.rst index c60554015b8..c73ed68c1ee 100644 --- a/book/performance.rst +++ b/book/performance.rst @@ -75,18 +75,16 @@ If you're using the Standard Distribution, this code should already be available as comments in this file:: // app.php - // ... - $loader = require __DIR__.'/../app/autoload.php'; - include_once __DIR__.'/../var/bootstrap.php.cache'; - // Enable APC for autoloading to improve performance. - // You should change the ApcClassLoader first argument to a unique prefix - // in order to prevent cache key conflicts with other applications - // also using APC. + + $loader = require_once __DIR__.'/../app/bootstrap.php.cache'; + + // Use APC for autoloading to improve performance + // Change 'sf2' by the prefix you want in order + // to prevent key conflict with another application /* - $apcLoader = new Symfony\Component\ClassLoader\ApcClassLoader(sha1(__FILE__), $loader); - $loader->unregister(); - $apcLoader->register(true); + $loader = new ApcClassLoader('sf2', $loader); + $loader->register(true); */ // ... @@ -121,7 +119,7 @@ If you're using the Symfony Standard Edition, then you're probably already using the bootstrap file. To be sure, open your front controller (usually ``app.php``) and check to make sure that the following line exists:: - include_once __DIR__.'/../var/bootstrap.php.cache'; + require_once __DIR__.'/../app/bootstrap.php.cache'; Note that there are two disadvantages when using a bootstrap file: diff --git a/book/routing.rst b/book/routing.rst index 30453bee220..aa08421c458 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -87,6 +87,10 @@ The route is simple: return $collection; +.. versionadded:: 2.2 + The ``path`` option was introduced in Symfony 2.2, ``pattern`` is used + in older versions. + The path defined by the ``blog_show`` route acts like ``/blog/*`` where the wildcard is given the name ``slug``. For the URL ``/blog/my-blog-post``, the ``slug`` variable gets a value of ``my-blog-post``, which is available @@ -638,11 +642,10 @@ URL Route Parameters ``/blog/my-blog-post`` ``blog`` ``{page}`` = ``"my-blog-post"`` ====================== ======== =============================== -The answer to the problem is to add route *requirements* or route *conditions* -(see :ref:`book-routing-conditions`). The routes in this example would work -perfectly if the ``/blog/{page}`` path *only* matched URLs where the ``{page}`` -portion is an integer. Fortunately, regular expression requirements can easily -be added for each parameter. For example: +The answer to the problem is to add route *requirements*. The routes in this +example would work perfectly if the ``/blog/{page}`` path *only* matched +URLs where the ``{page}`` portion is an integer. Fortunately, regular expression +requirements can easily be added for each parameter. For example: .. configuration-block:: @@ -896,6 +899,10 @@ accomplished with the following route configuration: return $collection; +.. versionadded:: 2.2 + The ``methods`` option was introduced in Symfony 2.2. Use the ``_method`` + requirement in older versions. + Despite the fact that these two routes have identical paths (``/api/posts/{id}``), the first route will match only GET or HEAD requests and the second route will match only PUT requests. This means that you can display @@ -909,96 +916,13 @@ two actions. Adding a Host Requirement ~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.2 + Host matching support was introduced in Symfony 2.2 + You can also match on the HTTP *host* of the incoming request. For more information, see :doc:`/components/routing/hostname_pattern` in the Routing component documentation. -.. _book-routing-conditions: - -Completely Customized Route Matching with Conditions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As you've seen, a route can be made to match only certain routing wildcards -(via regular expressions), HTTP methods, or host names. But the routing system -can be extended to have an almost infinite flexibility using ``conditions``: - -.. configuration-block:: - - .. code-block:: yaml - - contact: - path: /contact - defaults: { _controller: AcmeDemoBundle:Main:contact } - condition: "context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i'" - - .. code-block:: xml - - - - - - AcmeDemoBundle:Main:contact - context.getMethod() in ['GET', 'HEAD'] and request.headers.get('User-Agent') matches '/firefox/i' - - - - .. code-block:: php - - use Symfony\Component\Routing\RouteCollection; - use Symfony\Component\Routing\Route; - - $collection = new RouteCollection(); - $collection->add('contact', new Route( - '/contact', array( - '_controller' => 'AcmeDemoBundle:Main:contact', - ), - array(), - array(), - '', - array(), - array(), - 'context.getMethod() in ["GET", "HEAD"] and request.headers.get("User-Agent") matches "/firefox/i"' - )); - - return $collection; - -The ``condition`` is an expression, and you can learn more about its syntax -here: :doc:`/components/expression_language/syntax`. With this, the route -won't match unless the HTTP method is either GET or HEAD *and* if the ``User-Agent`` -header matches ``firefox``. - -You can do any complex logic you need in the expression by leveraging two -variables that are passed into the expression: - -``context`` - An instance of :class:`Symfony\\Component\\Routing\\RequestContext`, which - holds the most fundamental information about the route being matched. -``request`` - The Symfony :class:`Symfony\\Component\\HttpFoundation\\Request` object - (see :ref:`component-http-foundation-request`). - -.. caution:: - - Conditions are *not* taken into account when generating a URL. - -.. sidebar:: Expressions are Compiled to PHP - - Behind the scenes, expressions are compiled down to raw PHP. Our example - would generate the following PHP in the cache directory:: - - if (rtrim($pathinfo, '/contact') === '' && ( - in_array($context->getMethod(), array(0 => "GET", 1 => "HEAD")) - && preg_match("/firefox/i", $request->headers->get("User-Agent")) - )) { - // ... - } - - Because of this, using the ``condition`` key causes no extra overhead - beyond the time it takes for the underlying PHP to execute. - .. index:: single: Routing; Advanced example single: Routing; _format parameter @@ -1386,6 +1310,9 @@ be prefixed with the string ``/site``. Adding a Host Requirement to Imported Routes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.2 + Host matching support was introduced in Symfony 2.2 + You can set the host regex on imported routes. For more information, see :ref:`component-routing-host-imported`. @@ -1397,12 +1324,12 @@ Visualizing & Debugging Routes While adding and customizing routes, it's helpful to be able to visualize and get detailed information about your routes. A great way to see every route -in your application is via the ``debug:router`` console command. Execute +in your application is via the ``router:debug`` console command. Execute the command by running the following from the root of your project. .. code-block:: bash - $ php bin/console debug:router + $ php app/console router:debug This command will print a helpful list of *all* the configured routes in your application: @@ -1421,14 +1348,14 @@ the route name after the command: .. code-block:: bash - $ php bin/console debug:router article_show + $ php app/console router:debug article_show Likewise, if you want to test whether a URL matches a given route, you can use the ``router:match`` console command: .. code-block:: bash - $ php bin/console router:match /blog/my-latest-post + $ php app/console router:match /blog/my-latest-post This command will print which route the URL matches. @@ -1537,7 +1464,7 @@ a template helper function: .. code-block:: html+php -
    generate('blog_show', array( 'slug' => 'my-blog-post', )) ?>"> Read this blog post. @@ -1558,8 +1485,9 @@ method:: $this->generateUrl('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL); // http://www.example.com/blog/my-blog-post -From a template, simply use the ``url()`` function (which generates an absolute -URL) rather than the ``path()`` function (which generates a relative URL): +From a template, in Twig, simply use the ``url()`` function (which generates an absolute URL) +rather than the ``path()`` function (which generates a relative URL). In PHP, pass ``true`` +to ``generate()``: .. configuration-block:: @@ -1571,9 +1499,13 @@ URL) rather than the ``path()`` function (which generates a relative URL): .. code-block:: html+php - generate('blog_show', array( 'slug' => 'my-blog-post', - )) ?>"> + ), UrlGeneratorInterface::ABSOLUTE_URL) ?>"> Read this blog post. diff --git a/book/security.rst b/book/security.rst index e81df02bff7..acc2f90ad75 100644 --- a/book/security.rst +++ b/book/security.rst @@ -100,11 +100,6 @@ The ``firewalls`` key is the *heart* of your security configuration. The tools - which live under URLs like ``/_profiler`` and ``/_wdt`` aren't blocked by your security. -.. tip:: - - You can also match a request against other details of the request (e.g. host). For more - information and examples read :doc:`/cookbook/security/firewall_restriction`. - All other URLs will be handled by the ``default`` firewall (no ``pattern`` key means it matches *all* URLs). You can think of the firewall like your security system, and so it usually makes sense to have just one main firewall. @@ -510,12 +505,11 @@ else, you'll want to encode their passwords. The best algorithm to use is // ... )); -Of course, your users' passwords now need to be encoded with this exact algorithm. -For hardcoded users, you can use the built-in command: +.. include:: /cookbook/security/_ircmaxwell_password-compat.rst.inc -.. code-block:: bash - - $ php bin/console security:encode-password +Of course, your users' passwords now need to be encoded with this exact algorithm. +For hardcoded users, you can use an `online tool`_ (as it's a public tool, +avoid using real passwords). It will give you something like this: @@ -598,9 +592,6 @@ before inserting them into the database? Don't worry, see :doc:`Security Reference Section ` for examples. - It's also possible to use different hashing algorithms on a user-by-user - basis. See :doc:`/cookbook/security/named_encoders` for more details. - D) Configuration Done! ~~~~~~~~~~~~~~~~~~~~~~ @@ -687,7 +678,7 @@ There are **two** ways to deny access to something: allows you to protect URL patterns (e.g. ``/admin/*``). This is easy, but less flexible; -#. :ref:`in your code via the security.authorization_checker service `. +#. :ref:`in your code via the security.context service `. .. _security-authorization-access-control: @@ -830,55 +821,30 @@ Securing Controllers and other Code You can easily deny access from inside a controller:: // ... + use Symfony\Component\Security\Core\Exception\AccessDeniedException; public function helloAction($name) { - // The second parameter is used to specify on what object the role is tested. - $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); - - // Old way : - // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { - // throw $this->createAccessDeniedException('Unable to access this page!'); - // } + if (!$this->get('security.context')->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedException(); + } // ... } -In both cases, a special -:class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException` -is thrown, which ultimately triggers a 403 HTTP response inside Symfony. - That's it! If the user isn't logged in yet, they will be asked to login (e.g. redirected to the login page). If they *are* logged in, but do *not* have the ``ROLE_ADMIN`` role, they'll be shown the 403 access denied page (which you can :ref:`customize `). If they are logged in and have the correct roles, the code will be executed. -.. _book-security-securing-controller-annotations: - -Thanks to the SensioFrameworkExtraBundle, you can also secure your controller -using annotations:: - - // ... - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; - - /** - * @Security("has_role('ROLE_ADMIN')") - */ - public function helloAction($name) - { - // ... - } - -For more information, see the `FrameworkExtraBundle documentation`_. - .. _book-security-template: Access Control in Templates ........................... If you want to check if the current user has a role inside a template, use -the built-in ``is_granted()`` helper function: +the built-in helper function: .. configuration-block:: @@ -894,6 +860,20 @@ the built-in ``is_granted()`` helper function: Delete +If you use this function and you are *not* behind a firewall, an exception will +be thrown. Again, it's almost always a good idea to have a main firewall that +covers all URLs (as shown before in this chapter). + +.. caution:: + + Be careful with this in your base layout or on your error pages! Because of + some internal Symfony details, to avoid broken error pages in the ``prod`` + environment, wrap calls in these templates with a check for ``app.user``: + + .. code-block:: html+twig + + {% if app.user and is_granted('ROLE_ADMIN') %} + Securing other Services ....................... @@ -913,11 +893,12 @@ user is logged in (you don't care about roles), then you can use ``IS_AUTHENTICATED_FULLY``:: // ... + use Symfony\Component\Security\Core\Exception\AccessDeniedException; public function helloAction($name) { - if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { - throw $this->createAccessDeniedException(); + if (!$this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { + throw new AccessDeniedException(); } // ... @@ -944,30 +925,6 @@ special attributes like this: this - this is useful when *whitelisting* URLs to guarantee access - some details are in :doc:`/cookbook/security/access_control`. -.. _book-security-template-expression: - -You can also use expressions inside your templates: - -.. configuration-block:: - - .. code-block:: html+jinja - - {% if is_granted(expression( - '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' - )) %} - Delete - {% endif %} - - .. code-block:: html+php - - isGranted(new Expression( - '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())' - ))): ?> - Delete - - -For more details on expressions and security, see :ref:`book-security-expressions`. - .. _security-secure-objects: Access Control Lists (ACLs): Securing individual Database Objects @@ -997,19 +954,19 @@ Retrieving the User Object -------------------------- After authentication, the ``User`` object of the current user can be accessed -via the ``security.token_storage`` service. From inside a controller, this will +via the ``security.context`` service. From inside a controller, this will look like:: public function indexAction() { - if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { - throw $this->createAccessDeniedException(); + if (!$this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { + throw new AccessDeniedException(); } $user = $this->getUser(); // the above is a shortcut for this - $user = $this->get('security.token_storage')->getToken()->getUser(); + $user = $this->get('security.context')->getToken()->getUser(); } .. tip:: @@ -1044,8 +1001,8 @@ the User object, and use the ``isGranted`` method (or :ref:`access_control `) to do this:: // yay! Use this to see if the user is logged in - if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { - throw $this->createAccessDeniedException(); + if (!$this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) { + throw new AccessDeniedException(); } // boo :(. Never check for the User object to see if they're logged in @@ -1196,13 +1153,13 @@ the users' passwords before inserting them. No matter what algorithm you configure for your user object, the hashed password can always be determined in the following way from a controller:: + $factory = $this->get('security.encoder_factory'); // whatever *your* User object is $user = new AppBundle\Entity\User(); - $plainPassword = 'ryanpass'; - $encoder = $this->container->get('security.password_encoder'); - $encoded = $encoder->encodePassword($user, $plainPassword); - $user->setPassword($encoded); + $encoder = $factory->getEncoder($user); + $password = $encoder->encodePassword('ryanpass', $user->getSalt()); + $user->setPassword($password); In order for this to work, just make sure that you have the encoder for your user class (e.g. ``AppBundle\Entity\User``) configured under the ``encoders`` @@ -1334,40 +1291,6 @@ cookie will be ever created by Symfony): If you use a form login, Symfony will create a cookie even if you set ``stateless`` to ``true``. -.. _book-security-checking-vulnerabilities: - -Checking for Known Security Vulnerabilities in Dependencies -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When using lots of dependencies in your Symfony projects, some of them may -contain security vulnerabilities. That's why Symfony includes a command called -``security:check`` that checks your ``composer.lock`` file to find any known -security vulnerability in your installed dependencies: - -.. code-block:: bash - - $ php bin/console security:check - -A good security practice is to execute this command regularly to be able to -update or replace compromised dependencies as soon as possible. Internally, -this command uses the public `security advisories database`_ published by the -FriendsOfPHP organization. - -.. tip:: - - The ``security:check`` command terminates with a non-zero exit code if - any of your dependencies is affected by a known security vulnerability. - Therefore, you can easily integrate it in your build process. - -.. note:: - - To enable the ``security:check`` command, make sure the - `SensioDistributionBundle`_ is installed. - - .. code-block:: bash - - $ composer require 'sensio/distribution-bundle' - Final Words ----------- @@ -1394,7 +1317,6 @@ Learn More from the Cookbook * :doc:`/cookbook/security/remember_me` * :doc:`/cookbook/security/multiple_user_providers` +.. _`online tool`: https://www.dailycred.com/blog/12/bcrypt-calculator .. _`frameworkextrabundle documentation`: https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/index.html -.. _`security advisories database`: https://github.com/FriendsOfPHP/security-advisories .. _`HWIOAuthBundle`: https://github.com/hwi/HWIOAuthBundle -.. _`SensioDistributionBundle`: https://packagist.org/packages/sensio/distribution-bundle diff --git a/book/service_container.rst b/book/service_container.rst index a3439ff7a46..6fdc507eaa0 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -105,7 +105,41 @@ for you. In order for this to work, you must *teach* the container how to create the ``Mailer`` service. This is done via configuration, which can be specified in YAML, XML or PHP: -.. include:: includes/_service_container_my_mailer.rst.inc +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + app.mailer: + class: AppBundle\Mailer + arguments: [sendmail] + + .. code-block:: xml + + + + + + + + sendmail + + + + + .. code-block:: php + + // app/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $container->setDefinition('app.mailer', new Definition( + 'AppBundle\Mailer', + array('sendmail') + )); .. note:: @@ -145,7 +179,7 @@ As a bonus, the ``Mailer`` service is only created once and the same instance is returned each time you ask for the service. This is almost always the behavior you'll need (it's more flexible and powerful), but you'll learn later how you can configure a service that has multiple instances in the -":doc:`/cookbook/service_container/shared`" cookbook article. +":doc:`/cookbook/service_container/scopes`" cookbook article. .. note:: @@ -237,6 +271,14 @@ parameter and uses it in the service definition. http://symfony.com/?foo=%%s&bar=%%d +.. caution:: + + You may receive a + :class:`Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException` + when passing the ``request`` service as an argument. To understand this + problem better and learn how to solve it, refer to the cookbook article + :doc:`/cookbook/service_container/scopes`. + The purpose of parameters is to feed information into services. Of course there was nothing wrong with defining the service without using any parameters. Parameters, however, have several advantages: @@ -619,114 +661,6 @@ service needs the ``app.mailer`` service in order to function. When you define this dependency in the service container, the container takes care of all the work of instantiating the classes. -.. _book-services-expressions: - -Using the Expression Language -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The service container also supports an "expression" that allows you to inject -very specific values into a service. - -For example, suppose you have a third service (not shown here), called ``mailer_configuration``, -which has a ``getMailerMethod()`` method on it, which will return a string -like ``sendmail`` based on some configuration. Remember that the first argument -to the ``my_mailer`` service is the simple string ``sendmail``: - -.. include:: includes/_service_container_my_mailer.rst.inc - -But instead of hardcoding this, how could we get this value from the ``getMailerMethod()`` -of the new ``mailer_configuration`` service? One way is to use an expression: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/config.yml - services: - my_mailer: - class: Acme\HelloBundle\Mailer - arguments: ["@=service('mailer_configuration').getMailerMethod()"] - - .. code-block:: xml - - - - - - - - service('mailer_configuration').getMailerMethod() - - - - - .. code-block:: php - - // app/config/config.php - use Symfony\Component\DependencyInjection\Definition; - use Symfony\Component\ExpressionLanguage\Expression; - - $container->setDefinition('my_mailer', new Definition( - 'Acme\HelloBundle\Mailer', - array(new Expression('service("mailer_configuration").getMailerMethod()')) - )); - -To learn more about the expression language syntax, see :doc:`/components/expression_language/syntax`. - -In this context, you have access to 2 functions: - -``service`` - Returns a given service (see the example above). -``parameter`` - Returns a specific parameter value (syntax is just like ``service``). - -You also have access to the :class:`Symfony\\Component\\DependencyInjection\\ContainerBuilder` -via a ``container`` variable. Here's another example: - -.. configuration-block:: - - .. code-block:: yaml - - services: - my_mailer: - class: Acme\HelloBundle\Mailer - arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"] - - .. code-block:: xml - - - - - - - container.hasParameter('some_param') ? parameter('some_param') : 'default_value' - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Definition; - use Symfony\Component\ExpressionLanguage\Expression; - - $container->setDefinition('my_mailer', new Definition( - 'Acme\HelloBundle\Mailer', - array(new Expression( - "container.hasParameter('some_param') ? parameter('some_param') : 'default_value'" - )) - )); - -Expressions can be used in ``arguments``, ``properties``, as arguments with -``configurator`` and as arguments to ``calls`` (method calls). - Optional Dependencies: Setter Injection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -810,89 +744,6 @@ Injecting the dependency by the setter method just needs a change of syntax: and "setter injection". The Symfony service container also supports "property injection". -.. _book-container-request-stack: -.. _injecting-the-request: - -Accessing the Request in a Service -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Whenever you need to access the current request in a service, you can either -add it as an argument to the methods that need the request or inject the -``request_stack`` service and access the ``Request`` by calling the -:method:`Symfony\\Component\\HttpFoundation\\RequestStack::getCurrentRequest` -method:: - - namespace Acme\HelloBundle\Newsletter; - - use Symfony\Component\HttpFoundation\RequestStack; - - class NewsletterManager - { - protected $requestStack; - - public function __construct(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - } - - public function anyMethod() - { - $request = $this->requestStack->getCurrentRequest(); - // ... do something with the request - } - - // ... - } - -Now, just inject the ``request_stack``, which behaves like any normal service: - -.. configuration-block:: - - .. code-block:: yaml - - # src/Acme/HelloBundle/Resources/config/services.yml - services: - newsletter_manager: - class: Acme\HelloBundle\Newsletter\NewsletterManager - arguments: ["@request_stack"] - - .. code-block:: xml - - - - - - - - - - - - - .. code-block:: php - - // src/Acme/HelloBundle/Resources/config/services.php - use Symfony\Component\DependencyInjection\Definition; - use Symfony\Component\DependencyInjection\Reference; - - // ... - $container->setDefinition('newsletter_manager', new Definition( - 'Acme\HelloBundle\Newsletter\NewsletterManager', - array(new Reference('request_stack')) - )); - -.. tip:: - - If you define a controller as a service then you can get the ``Request`` - object without injecting the container by having it passed in as an - argument of your action method. See - :ref:`book-controller-request-argument` for details. - Making References optional -------------------------- @@ -1136,18 +987,18 @@ console. To show all services and the class for each service, run: .. code-block:: bash - $ php bin/console debug:container + $ php app/console container:debug By default, only public services are shown, but you can also view private services: .. code-block:: bash - $ php bin/console debug:container --show-private + $ php app/console container:debug --show-private .. note:: If a private service is only used as an argument to just *one* other service, - it won't be displayed by the ``debug:container`` command, even when using + it won't be displayed by the ``container:debug`` command, even when using the ``--show-private`` option. See :ref:`Inline Private Services ` for more details. @@ -1156,7 +1007,7 @@ its id: .. code-block:: bash - $ php bin/console debug:container app.mailer + $ php app/console container:debug app.mailer Learn more ---------- @@ -1168,6 +1019,7 @@ Learn more * :doc:`/components/dependency_injection/parentservices` * :doc:`/components/dependency_injection/tags` * :doc:`/cookbook/controller/service` +* :doc:`/cookbook/service_container/scopes` * :doc:`/cookbook/service_container/compiler_passes` * :doc:`/components/dependency_injection/advanced` diff --git a/book/templating.rst b/book/templating.rst index be8167e5a89..4d99b4dc9bc 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -159,7 +159,7 @@ Twig Template Caching Twig is fast. Each Twig template is compiled down to a native PHP class that is rendered at runtime. The compiled classes are located in the -``var/cache/{environment}/twig`` directory (where ``{environment}`` is the +``app/cache/{environment}/twig`` directory (where ``{environment}`` is the environment, such as ``dev`` or ``prod``) and in some cases can be useful while debugging. See :ref:`environments-summary` for more information on environments. @@ -379,6 +379,11 @@ When working with template inheritance, here are some tips to keep in mind: Template Naming and Locations ----------------------------- +.. versionadded:: 2.2 + Namespaced path support was introduced in 2.2, allowing for template names + like ``@AcmeDemo/layout.html.twig``. See :doc:`/cookbook/templating/namespaced_paths` + for more details. + By default, templates can live in two different locations: ``app/Resources/views/`` @@ -579,6 +584,10 @@ you set `with_context`_ to false). maps (i.e. an array with named keys). If you needed to pass in multiple elements, it would look like this: ``{'foo': foo, 'bar': bar}``. +.. versionadded:: 2.3 + The `include() function`_ is available since Symfony 2.3. Prior, the + `{% include %} tag`_ was used. + .. index:: single: Templating; Embedding action @@ -686,6 +695,9 @@ that as much code as possible lives in reusable :doc:`services render( - $view['router']->url('...'), + $view['router']->generate('...'), array('renderer' => 'hinclude') ) ?> @@ -793,6 +805,9 @@ in your application configuration: ), )); +.. versionadded:: 2.2 + Default templates per render function was introduced in Symfony 2.2 + You can define default templates per ``render`` function (which will override any global default template that is defined): @@ -914,7 +929,7 @@ To link to the page, just use the ``path`` Twig function and refer to the route: .. code-block:: html+php - Home + Home As expected, this will generate the URL ``/``. Now, for a more complicated route: @@ -993,7 +1008,7 @@ correctly: - generate('article_show', array( 'slug' => $article->getSlug(), )) ?>"> getTitle() ?> @@ -1002,20 +1017,26 @@ correctly: .. tip:: - You can also generate an absolute URL by using the ``url`` function: + You can also generate an absolute URL by using the ``url`` Twig function: - .. configuration-block:: + .. code-block:: html+twig - .. code-block:: html+twig + Home - Home + The same can be done in PHP templates by passing a third argument to + the ``generate()`` method: - .. code-block:: html+php + .. code-block:: html+php + + - Home + Home .. index:: single: Templating; Linking to assets @@ -1057,47 +1078,6 @@ assets won't be loaded from cache after being deployed. For example, ``/images/l look like ``/images/logo.png?v2``. For more information, see the :ref:`reference-framework-assets-version` configuration option. -.. _`book-templating-version-by-asset`: - -If you need to set a version for a specific asset, you can set the ``version`` argument -if you are using Twig (or the fourth argument if you are using PHP) to the desired version: - -.. configuration-block:: - - .. code-block:: html+jinja - - Symfony! - - .. code-block:: html+php - - Symfony! - -If you don't give a version or pass ``null``, the default package version -(from :ref:`reference-framework-assets-version`) will be used. If you pass ``false``, -versioned URL will be deactivated for this asset. - -If you need absolute URLs for assets, you can use the ``absolute_url`` function -if you are using Twig (or the third argument if you are using PHP) to ``true``: - -.. configuration-block:: - - .. code-block:: html+jinja - - Symfony! - - .. code-block:: html+php - - Symfony! - .. index:: single: Templating; Including stylesheets and JavaScripts single: Stylesheets; Including stylesheets @@ -1113,9 +1093,9 @@ advantage of Symfony's template inheritance. .. tip:: This section will teach you the philosophy behind including stylesheet - and JavaScript assets in Symfony. Symfony is also compatible with another - library, called Assetic, which follows this philosophy but allows you to do - much more interesting things with those assets. For more information on + and JavaScript assets in Symfony. Symfony also packages another library, + called Assetic, which follows this philosophy but allows you to do much + more interesting things with those assets. For more information on using Assetic see :doc:`/cookbook/assetic/asset_management`. Start by adding two blocks to your base template that will hold your assets: @@ -1201,7 +1181,7 @@ should use the ``parent()`` Twig function to include everything from the ``style block of the base template. You can also include assets located in your bundles' ``Resources/public`` folder. -You will need to run the ``php bin/console assets:install target [--symlink]`` +You will need to run the ``php app/console assets:install target [--symlink]`` command, which moves (or symlinks) files into the correct location. (target is by default "web"). @@ -1221,6 +1201,8 @@ is a :class:`Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables` instance which will give you access to some application specific variables automatically: +``app.security`` + The security context. ``app.user`` The current user object. ``app.request`` @@ -1373,7 +1355,7 @@ to create it). You're now free to customize the template. .. caution:: If you add a template in a new location, you *may* need to clear your - cache (``php bin/console cache:clear``), even if you are in debug mode. + cache (``php app/console cache:clear``), even if you are in debug mode. This logic also applies to base bundle templates. Suppose also that each template in AcmeBlogBundle inherits from a base template called @@ -1571,33 +1553,12 @@ in a JavaScript string, use the ``js`` context: Debugging --------- -When using PHP, you can use the -:ref:`dump() function from the VarDumper component ` -if you need to quickly find the value of a variable passed. This is useful, -for example, inside your controller:: - - // src/AppBundle/Controller/ArticleController.php - namespace AppBundle\Controller; - - // ... - - class ArticleController extends Controller - { - public function recentListAction() - { - $articles = ...; - dump($articles); - - // ... - } - } - -.. note:: - - The output of the ``dump()`` function is then rendered in the web developer - toolbar. +When using PHP, you can use :phpfunction:`var_dump` if you need to quickly find +the value of a variable passed. This is useful, for example, inside your +controller. The same can be achieved when using Twig thanks to the Debug +extension. -The same mechanism can be used in Twig templates thanks to ``dump`` function: +Template parameters can then be dumped using the ``dump`` function: .. code-block:: html+twig @@ -1617,16 +1578,16 @@ is ``true``. By default this means that the variables will be dumped in the Syntax Checking --------------- -You can check for syntax errors in Twig templates using the ``lint:twig`` +You can check for syntax errors in Twig templates using the ``twig:lint`` console command: .. code-block:: bash # You can check by filename: - $ php bin/console lint:twig app/Resources/views/article/recent_list.html.twig + $ php app/console twig:lint app/Resources/views/article/recent_list.html.twig # or by directory: - $ php bin/console lint:twig app/Resources/views + $ php app/console twig:lint app/Resources/views .. _template-formats: @@ -1678,7 +1639,7 @@ key in the parameter hash: .. code-block:: html+php - generate('article_show', array( 'id' => 123, '_format' => 'pdf', )) ?>"> diff --git a/book/testing.rst b/book/testing.rst index fc9a66f6cd7..5d088e7345a 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -21,16 +21,18 @@ it has its own excellent `documentation`_. to use version 4.2 or higher to test the Symfony core code itself). Each test - whether it's a unit test or a functional test - is a PHP class -that should live in the ``tests/`` directory of your application. If you follow +that should live in the ``Tests/`` subdirectory of your bundles. If you follow this rule, then you can run all of your application's tests with the following command: .. code-block:: bash - $ phpunit + # specify the configuration directory on the command line + $ phpunit -c app/ -PHPunit is configured by the ``phpunit.xml.dist`` file in the root of your -Symfony application. +The ``-c`` option tells PHPUnit to look in the ``app/`` directory for a configuration +file. If you're curious about the PHPUnit options, check out the ``app/phpunit.xml.dist`` +file. .. tip:: @@ -62,11 +64,11 @@ called ``Calculator`` in the ``Util/`` directory of the app bundle:: } } -To test this, create a ``CalculatorTest`` file in the ``tests/AppBundle/Util`` directory +To test this, create a ``CalculatorTest`` file in the ``Tests/Util`` directory of your bundle:: - // tests/AppBundle/Util/CalculatorTest.php - namespace Tests\AppBundle\Util; + // src/AppBundle/Tests/Util/CalculatorTest.php + namespace AppBundle\Tests\Util; use AppBundle\Util\Calculator; @@ -84,30 +86,30 @@ of your bundle:: .. note:: - By convention, the ``Tests/AppBundle`` directory should replicate the directory - of your bundle for unit tests. So, if you're testing a class in the - ``AppBundle/Util/`` directory, put the test in the ``tests/AppBundle/Util/`` + By convention, the ``Tests/`` sub-directory should replicate the directory + of your bundle for unit tests. So, if you're testing a class in your + bundle's ``Util/`` directory, put the test in the ``Tests/Util/`` directory. Just like in your real application - autoloading is automatically enabled -via the ``autoload.php`` file (as configured by default in the -``phpunit.xml.dist`` file). +via the ``bootstrap.php.cache`` file (as configured by default in the +``app/phpunit.xml.dist`` file). Running tests for a given file or directory is also very easy: .. code-block:: bash # run all tests of the application - $ phpunit + $ phpunit -c app # run all tests in the Util directory - $ phpunit tests/AppBundle/Util + $ phpunit -c app src/AppBundle/Tests/Util # run tests for the Calculator class - $ phpunit tests/AppBundle/Util/CalculatorTest.php + $ phpunit -c app src/AppBundle/Tests/Util/CalculatorTest.php # run all tests for the entire Bundle - $ phpunit tests/AppBundle/ + $ phpunit -c app src/AppBundle/ .. index:: single: Tests; Functional tests @@ -128,15 +130,15 @@ tests as far as PHPUnit is concerned, but they have a very specific workflow: Your First Functional Test ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Functional tests are simple PHP files that typically live in the ``tests/AppBundle/Controller`` -directory for your bundle. If you want to test the pages handled by your +Functional tests are simple PHP files that typically live in the ``Tests/Controller`` +directory of your bundle. If you want to test the pages handled by your ``PostController`` class, start by creating a new ``PostControllerTest.php`` file that extends a special ``WebTestCase`` class. As an example, a test could look like this:: - // tests/AppBundle/Controller/PostControllerTest.php - namespace Tests\AppBundle\Controller; + // src/AppBundle/Tests/Controller/PostControllerTest.php + namespace AppBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; @@ -242,10 +244,6 @@ document:: To get you started faster, here is a list of the most common and useful test assertions:: - use Symfony\Component\HttpFoundation\Response; - - // ... - // Assert that there is at least one h2 tag // with the class "subtitle" $this->assertGreaterThan( @@ -275,7 +273,7 @@ document:: $this->assertTrue($client->getResponse()->isNotFound()); // Assert a specific 200 status code $this->assertEquals( - 200, // or Symfony\Component\HttpFoundation\Response::HTTP_OK + 200, $client->getResponse()->getStatusCode() ); @@ -420,6 +418,11 @@ The Client supports many operations that can be done in a real browser:: Accessing Internal Objects ~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + The :method:`Symfony\\Component\\BrowserKit\\Client::getInternalRequest` + and :method:`Symfony\\Component\\BrowserKit\\Client::getInternalResponse` + methods were introduced in Symfony 2.3. + If you use the client to test your application, you might want to access the client's internal objects:: @@ -460,7 +463,7 @@ Injection Container:: Be warned that this does not work if you insulate the client or if you use an HTTP layer. For a list of services available in your application, use the -``debug:container`` console task. +``container:debug`` console task. .. tip:: @@ -687,11 +690,6 @@ their type:: // Upload a file $form['photo']->upload('/path/to/lucas.jpg'); -.. tip:: - - If you purposefully want to select "invalid" select/radio values, see - :ref:`components-dom-crawler-invalid`. - .. tip:: You can get the values that will be submitted by calling the ``getValues()`` @@ -789,26 +787,30 @@ PHPUnit Configuration ~~~~~~~~~~~~~~~~~~~~~ Each application has its own PHPUnit configuration, stored in the -``phpunit.xml.dist`` file. You can edit this file to change the defaults or -create an ``phpunit.xml`` file to set up a configuration for your local machine -only. +``app/phpunit.xml.dist`` file. You can edit this file to change the defaults or +create an ``app/phpunit.xml`` file to set up a configuration for your local +machine only. .. tip:: - Store the ``phpunit.xml.dist`` file in your code repository and ignore - the ``phpunit.xml`` file. + Store the ``app/phpunit.xml.dist`` file in your code repository and ignore + the ``app/phpunit.xml`` file. -By default, only the tests stored in ``/tests`` are run via the ``phpunit`` command, -as configured in the ``phpunit.xml.dist`` file: +By default, only the tests from your own custom bundles stored in the standard +directories ``src/*/*Bundle/Tests``, ``src/*/Bundle/*Bundle/Tests``, +``src/*Bundle/Tests`` are run by the ``phpunit`` command, as configured +in the ``app/phpunit.xml.dist`` file: .. code-block:: xml - + - tests + ../src/*/*Bundle/Tests + ../src/*/Bundle/*Bundle/Tests + ../src/*Bundle/Tests @@ -819,7 +821,7 @@ configuration adds tests from a custom ``lib/tests`` directory: .. code-block:: xml - + @@ -836,7 +838,7 @@ section: .. code-block:: xml - + diff --git a/book/translation.rst b/book/translation.rst index e21f5b7084d..9855c599658 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -12,13 +12,11 @@ wrapping each with a function capable of translating the text (or "message") into the language of the user:: // text will *always* print out in English - dump('Hello World'); - die(); + var_dump('Hello World'); // text can be translated into the end-user's language or // default to English - dump($translator->trans('Hello World')); - die(); + var_dump($translator->trans('Hello World')); .. note:: @@ -313,6 +311,9 @@ texts* and complex expressions: Note that this only influences the current template, not any "included" template (in order to avoid side effects). +.. versionadded:: 2.1 + The ``trans_default_domain`` tag was introduced in Symfony 2.1. + PHP Templates ~~~~~~~~~~~~~ @@ -334,7 +335,7 @@ The translator service is accessible in PHP templates through the Translation Resource/File Names and Locations --------------------------------------------- -Symfony looks for message files (i.e. translations) in the following default locations: +Symfony looks for message files (i.e. translations) in the following locations: * the ``app/Resources/translations`` directory; @@ -372,51 +373,6 @@ The choice of which loader to use is entirely up to you and is a matter of taste. The recommended option is to use ``xlf`` for translations. For more options, see :ref:`component-translator-message-catalogs`. -.. note:: - - You can add other directories with the ``paths`` option in the configuration: - - .. configuration-block:: - - .. code-block:: yaml - - # app/config/config.yml - framework: - translator: - paths: - - '%kernel.root_dir%/../translations' - - .. code-block:: xml - - - - - - - - %kernel.root_dir%/../translations - - - - - .. code-block:: php - - // app/config/config.php - $container->loadFromExtension('framework', array( - 'translator' => array( - 'paths' => array( - '%kernel.root_dir%/../translations', - ), - ), - )); - .. note:: You can also store translations in a database, or any other storage by @@ -432,7 +388,7 @@ For more options, see :ref:`component-translator-message-catalogs`. .. code-block:: bash - $ php bin/console cache:clear + $ php app/console cache:clear .. _book-translation-fallback: @@ -452,12 +408,6 @@ checks translation resources for several locales: #. If the translation still isn't found, Symfony uses the ``fallbacks`` configuration parameter, which defaults to ``en`` (see `Configuration`_). -.. note:: - - When Symfony doesn't find a translation in the given locale, it will - add the missing translation to the log file. For details, - see :ref:`reference-framework-translator-logging`. - .. _book-translation-user-locale: Handling the User's Locale @@ -615,6 +565,11 @@ the framework: 'default_locale' => 'en', )); +.. versionadded:: 2.1 + The ``default_locale`` parameter was defined under the session key + originally, however, as of 2.1 this has been moved. This is because the + locale is now set on the request instead of the session. + .. _book-translation-constraint-messages: Translating Constraint Messages @@ -740,171 +695,6 @@ The translation of database content should be handled by Doctrine through the `Translatable Extension`_ or the `Translatable Behavior`_ (PHP 5.4+). For more information, see the documentation for these libraries. -Debugging Translations ----------------------- - -When maintaining a bundle, you may use or remove the usage of a translation -message without updating all message catalogues. The ``debug:translation`` -command helps you to find these missing or unused translation messages for a -given locale. It shows you a table with the result when translating the -message in the given locale and the result when the fallback would be used. -On top of that, it also shows you when the translation is the same as the -fallback translation (this could indicate that the message was not correctly -translated). - -Thanks to the messages extractors, the command will detect the translation -tag or filter usages in Twig templates: - -.. code-block:: jinja - - {% trans %}Symfony2 is great{% endtrans %} - - {{ 'Symfony2 is great'|trans }} - - {{ 'Symfony2 is great'|transchoice(1) }} - - {% transchoice 1 %}Symfony2 is great{% endtranschoice %} - -It will also detect the following translator usages in PHP templates: - -.. code-block:: php - - $view['translator']->trans("Symfony2 is great"); - - $view['translator']->transChoice('Symfony2 is great', 1); - -.. caution:: - - The extractors are not able to inspect the messages translated outside templates which means - that translator usages in form labels or inside your controllers won't be detected. - Dynamic translations involving variables or expressions are not detected in templates, - which means this example won't be analyzed: - - .. code-block:: jinja - - {% set message = 'Symfony2 is great' %} - {{ message|trans }} - -Suppose your application's default_locale is ``fr`` and you have configured ``en`` as the fallback locale -(see :ref:`book-translation-configuration` and :ref:`book-translation-fallback` for how to configure these). -And suppose you've already setup some translations for the ``fr`` locale inside an AcmeDemoBundle: - -.. configuration-block:: - - .. code-block:: xml - - - - - - - - Symfony2 is great - J'aime Symfony2 - - - - - - - .. code-block:: yaml - - # src/Acme/AcmeDemoBundle/Resources/translations/messages.fr.yml - Symfony2 is great: J'aime Symfony2 - - .. code-block:: php - - // src/Acme/AcmeDemoBundle/Resources/translations/messages.fr.php - return array( - 'Symfony2 is great' => 'J\'aime Symfony2', - ); - -and for the ``en`` locale: - -.. configuration-block:: - - .. code-block:: xml - - - - - - - - Symfony2 is great - Symfony2 is great - - - - - - .. code-block:: yaml - - # src/Acme/AcmeDemoBundle/Resources/translations/messages.en.yml - Symfony2 is great: Symfony2 is great - - .. code-block:: php - - // src/Acme/AcmeDemoBundle/Resources/translations/messages.en.php - return array( - 'Symfony2 is great' => 'Symfony2 is great', - ); - -To inspect all messages in the ``fr`` locale for the AcmeDemoBundle, run: - -.. code-block:: bash - - $ php bin/console debug:translation fr AcmeDemoBundle - -You will get this output: - -.. image:: /images/book/translation/debug_1.png - :align: center - -It indicates that the message ``Symfony2 is great`` is unused because it is translated, -but you haven't used it anywhere yet. - -Now, if you translate the message in one of your templates, you will get this output: - -.. image:: /images/book/translation/debug_2.png - :align: center - -The state is empty which means the message is translated in the ``fr`` locale and used in one or more templates. - -If you delete the message ``Symfony2 is great`` from your translation file for the ``fr`` locale -and run the command, you will get: - -.. image:: /images/book/translation/debug_3.png - :align: center - -The state indicates the message is missing because it is not translated in the ``fr`` locale -but it is still used in the template. -Moreover, the message in the ``fr`` locale equals to the message in the ``en`` locale. -This is a special case because the untranslated message id equals its translation in the ``en`` locale. - -If you copy the content of the translation file in the ``en`` locale, to the translation file -in the ``fr`` locale and run the command, you will get: - -.. image:: /images/book/translation/debug_4.png - :align: center - -You can see that the translations of the message are identical in the ``fr`` and ``en`` locales -which means this message was probably copied from French to English and maybe you forgot to translate it. - -By default all domains are inspected, but it is possible to specify a single domain: - -.. code-block:: bash - - $ php bin/console debug:translation en AcmeDemoBundle --domain=messages - -When bundles have a lot of messages, it is useful to display only the unused -or only the missing messages, by using the ``--only-unused`` or ``--only-missing`` switches: - -.. code-block:: bash - - $ php bin/console debug:translation en AcmeDemoBundle --only-unused - $ php bin/console debug:translation en AcmeDemoBundle --only-missing - Summary ------- diff --git a/book/validation.rst b/book/validation.rst index e4b9d2c8579..417fd026056 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -225,14 +225,14 @@ workflow looks like the following from inside a controller:: public function updateAction(Request $request) { $author = new Author(); - $form = $this->createForm(AuthorType::class, $author); + $form = $this->createForm(new AuthorType(), $author); $form->handleRequest($request); if ($form->isValid()) { // the validation passed, do something with the $author object - return $this->redirectToRoute(...); + return $this->redirect($this->generateUrl(...)); } return $this->render('author/form.html.twig', array( @@ -604,8 +604,8 @@ Getters Constraints can also be applied to the return value of a method. Symfony allows you to add a constraint to any public method whose name starts with -"get", "is" or "has". In this guide, these types of methods are referred to -as "getters". +"get" or "is". In this guide, both of these types of methods are referred +to as "getters". The benefit of this technique is that it allows you to validate your object dynamically. For example, suppose you want to make sure that a password field @@ -686,9 +686,9 @@ Now, create the ``isPasswordLegal()`` method and include the logic you need:: .. note:: The keen-eyed among you will have noticed that the prefix of the getter - ("get", "is" or "has") is omitted in the mapping. This allows you to move - the constraint to a property with the same name later (or vice versa) - without changing your validation logic. + ("get" or "is") is omitted in the mapping. This allows you to move the + constraint to a property with the same name later (or vice versa) without + changing your validation logic. .. _validation-class-target: @@ -875,11 +875,11 @@ the class name or the string ``Default``. constraints in the ``BaseUser`` class will be validated. To tell the validator to use a specific group, pass one or more group names -as the third argument to the ``validate()`` method:: +as the second argument to the ``validate()`` method:: - $errors = $validator->validate($author, null, array('registration')); + $errors = $validator->validate($author, array('registration')); -If no groups are specified, all constraints that belong to the group ``Default`` +If no groups are specified, all constraints that belong in group ``Default`` will be applied. Of course, you'll usually work with validation indirectly through the form @@ -1239,7 +1239,7 @@ it looks like this:: $emailConstraint->message = 'Invalid email address'; // use the validator to validate the value - $errorList = $this->get('validator')->validate( + $errorList = $this->get('validator')->validateValue( $email, $emailConstraint ); @@ -1256,13 +1256,13 @@ it looks like this:: // ... } -By calling ``validate`` on the validator, you can pass in a raw value and +By calling ``validateValue`` on the validator, you can pass in a raw value and the constraint object that you want to validate that value against. A full list of the available constraints - as well as the full class name for each constraint - is available in the :doc:`constraints reference ` section. -The ``validate`` method returns a :class:`Symfony\\Component\\Validator\\ConstraintViolationList` +The ``validateValue`` method returns a :class:`Symfony\\Component\\Validator\\ConstraintViolationList` object, which acts just like an array of errors. Each error in the collection is a :class:`Symfony\\Component\\Validator\\ConstraintViolation` object, which holds the error message on its ``getMessage`` method. diff --git a/changelog.rst b/changelog.rst index 129366565c0..aaf5f355962 100644 --- a/changelog.rst +++ b/changelog.rst @@ -19,37 +19,23 @@ March, 2016 New Documentation ~~~~~~~~~~~~~~~~~ -* `#6274 `_ Update Doctrine UTF8 docs (mcfedr) -* `#6282 `_ [Form] fix ``choice_label`` values (HeahDude) * `#5894 `_ [WIP] Added an article to explain how to upgrade third-party bundles to Symfony 3 (javiereguiluz) -* `#6273 `_ [PHPUnit bridge] Add documentation for the component (theofidry) * `#6291 `_ fortrabbit deployment guide + index listing (ostark) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -* `#6377 `_ Update "bootstrap.php.cache" to "autoload.php" (guilliamxavier) -* `#6368 `_ [cookbook] Made list of form types more consistent (AAstakhov) * `#6366 `_ Removed server:stop code block for 2.3 (theyoux) -* `#6347 `_ Add a note about enabling DebugBundle to use VarDumper inside Symfony (martijn80, javiereguiluz) -* `#6320 `_ Fixed typo in path (timhovius) * `#6334 `_ Fixed yaml configuration of app.exception_controller (AAstakhov) -* `#6322 `_ [DependencyInjection] fix autowiring docs (eXtreme) * `#6315 `_ Remove third parameter from createFormBuilder call (Hocdoc) -* `#6324 `_ Fixed UserCheckerInterface importing (VIs-a-vis) -* `#6326 `_ Missing svn:ignore (f-plante) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `#6404 `_ fixed a typo (RickieL) -* `#6409 `_ Update 'date' to DateType::class in form.rst (iltar) * `#6411 `_ Fixed a typo in configuration-block (VarunAgw) * `#6414 `_ stick to Sphinx 1.3.x for the moment (xabbuh) -* `#6399 `_ Fixed wrong code examples for Isbn constraint (AAstakhov) * `#6397 `_ Fix typo in SwitchUserListener file name (luxifer) -* `#6390 `_ Reworded the example about $deep param (Oliboy50, javiereguiluz) -* `#6381 `_ [Form] [Cookbook] Correctly setup unit tests with dependencies (corphi) * `#6382 `_ unused use instructions (bshevchenko) * `#6365 `_ Removed the PR table example (this is now included by GitHub template) (javiereguiluz) * `#6363 `_ Removed info about reducing visibility for private (AAstakhov) @@ -67,20 +53,13 @@ Minor Documentation Changes * `#6345 `_ Remove link-local IPv6 address (snoek09) * `#6219 `_ Point that route parameters are also Request attributes (sfdumi) * `#6348 `_ [best practices] mostly typos (Talita Kocjan Zager) -* `#6350 `_ Fix reference to app folder (kainjow) * `#6275 `_ [quick tour] mostly typos (Talita Kocjan Zager) * `#6305 `_ Mention IvoryCKEditorBundle in the Symfony Forms doc (javiereguiluz) -* `#6331 `_ Rename DunglasApiBundle to ApiPlatform (sroze) * `#6328 `_ Update extension.rst - added caution box for people trying to remove the default file with services definitions (Pavel Jurecka) * `#6343 `_ Replace XLIFF number ids by strings (Triiistan) * `#6344 `_ Altered single / multiple inheritance sentence (outspaced) -* `#6330 `_ [Form] reorder EntityType options (HeahDude) * `#6337 `_ Fix configuration.rst typo (gong023) * `#6295 `_ Update tools.rst (andrewtch) -* `#6323 `_ [DependencyInjection] Add Autowiring keyword (theofidry) -* `#6325 `_ Minor error (ThomasLandauer) -* `#6311 `_ Improved TwigExtension to show default values and optional arguments (javiereguiluz) -* `#6286 `_ [HttpFoundation] Fix typo for ParameterBag getters - 3.0 (rendler-denis) * `#6267 `_ [Form] fix 'data_class' option in EntityType (HeahDude) * `#6281 `_ Change isValid to isSubmitted. (mustafaaloko) @@ -91,91 +70,54 @@ February, 2016 New Documentation ~~~~~~~~~~~~~~~~~ -* `#6172 `_ move assets options from templating to assets section and add base_path documentation (snoek09) * `#6021 `_ mention routing from the database (dbu) -* `#6032 `_ [DependencyInjection] Autowiring doc (dunglas) -* `#6233 `_ Document translation_domain for choice fields (merorafael, WouterJ) * `#5655 `_ Added doc about Homestead's Symfony integration (WouterJ) -* `#5886 `_ [2.8] Add "How to Use Multiple Guard Authenticators" cookbook documentation (mheki) * `#6072 `_ Add browserkit component documentation (yamiko, yamiko-ninja, robert Parker, javiereguiluz) -* `#6243 `_ Add missing getBoolean() method (bocharsky-bw) * `#6231 `_ Use hash_equals instead of StringUtils::equals (WouterJ) -* `#5530 `_ [Cookbook, Security] Added user_checkers.rst (iltar) -* `#5920 `_ Document automatic registration of extension compiler passes (WouterJ) * `#5724 `_ Describe configuration behaviour with multiple mailers (xelan) -* `#6077 `_ fixes #5971 (vincentaubert) -* `#5483 `_ [FrameworkBundle] Name converter of Serializer (dunglas) * `#6156 `_ [reference] [form] [options] fix #6153 (HeahDude) * `#6104 `_ Fix #6103 (zsturgess) -* `#6058 `_ Update Testing Form Types article for 2.8 refactorings (WouterJ) * `#5856 `_ Reworded the "How to use Gmail" cookbook article (javiereguiluz) * `#6230 `_ Add annotation to glossary (rebased) (DerStoffel) -* `#5642 `_ Documented label_format option (WouterJ) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -* `#6292 `_ Fix setting permission for var subdirectories (voda) * `#5995 `_ Update dev_environment.rst (gonzalovilaseca) * `#6240 `_ [#6224] some tweaks (xabbuh) * `#5513 `_ [load_balancer_reverse_proxy ] Always use 127.0.0.1 as a trusted proxy (ruudk) -* `#6081 `_ [cookbook New project] Fix symfony version and initial add (bigs21) * `#6124 `_ [cookbook] Add annotations block and fix regex (peterkokot) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `#6308 `_ fix literal syntax (xabbuh) -* `#6299 `_ Removed True and False constraints from reference (edefimov) -* `#6298 `_ Update dependency_injection.rst because it has an error. (joserprieto) -* `#6263 `_ [Cookbook][Debugging] reflect behavior changes in cache generation (xabbuh) * `#6251 `_ To use annotations, files must be removed (pbowyer) * `#6288 `_ Update factories.rst (velikanov) * `#6278 `_ [HttpFoundation] Fix typo for ParameterBag getters (rendler-denis) -* `#6280 `_ Fix syntax of Company class example (cakper) * `#6284 `_ [Book] [Routing] Fix third param true to UrlGeneratorInterface::ABSOLUTE_URI (eriwin) * `#6269 `_ [Cookbook][Bundles]fix yaml syntax (mhor) -* `#6277 `_ remove dot in front of colon (xabbuh) * `#6255 `_ [Cookbook][Doctrine] some tweaks to the Doctrine registration article (xabbuh) * `#6229 `_ Rewrite EventDispatcher introduction (WouterJ) -* `#6260 `_ add missing options `choice_value`, `choice_name` and `choice_attr` to `EntityType` (HeahDude) -* `#6262 `_ [Form] reorder options in choice types references (HeahDude) * `#6256 `_ Fixed code example (twifty) -* `#6257 `_ [Components][Form] remove outdated caution (xabbuh) -* `#6253 `_ [Security] Include guard firewall configuration sample. (calinpristavu) * `#6250 `_ [Cookbook][Console] remove note about memory spool handling on CLI (xabbuh) -* `#6249 `_ [Cookbook][Serializer] fix wording (xabbuh) -* `#6242 `_ Removed all 2.x versionadded directives (WouterJ) * `#6246 `_ removed duplicate lines (seferov) * `#6222 `_ Updated "Learn more from the Cookbook" section (sfdumi) -* `#6245 `_ [Cookbook][Console] change API doc class name (xabbuh) * `#6223 `_ Improveme the apache/mod_php configuration example (gnat42) * `#6234 `_ File System Security Issue in Custom Auth Article (finished) (mattjanssen, WouterJ) * `#4773 `_ [Cookbook] Make registration_form follow best practices (xelaris) -* `#6090 `_ Reworded the article about profiler storage (xavierleune, javiereguiluz) * `#5630 `_ Add a caution about logout when using http-basic authenticated firewall (rmed19) * `#6215 `_ Added a caution about failing cache warmers (javiereguiluz) * `#6239 `_ Remove app_dev as build-in server is used (rmed19, WouterJ) -* `#6241 `_ [ExpressionLanguage] Add caution about backslash handling (zerustech, WouterJ) -* `#6235 `_ #6232 update forms as services section (backbone87) * `#6236 `_ fix some minor typos (xabbuh) -* `#6237 `_ use literals for external class names (xabbuh) -* `#6206 `_ add separate placeholder examples for birthday, datetime and time type (snoek09) * `#6238 `_ fix directive name (xabbuh) * `#6224 `_ Note to create a service if you extend ExceptionController (pamuche) * `#5958 `_ Update security.rst (mpaquet) * `#6092 `_ Updated information about testing code coverage. (roga) * `#6051 `_ Mention HautelookAliceBundle in best practices (theofidry, WouterJ) -* `#6044 `_ Added note about the hash_equals polyfill (WouterJ) -* `#6213 `_ Update form_collections.rst (insekticid) -* `#6220 `_ [book] fixes typo about redirect status codes in the controller chapter. (hhamon) * `#6227 `_ Update testing.rst (dvapelnik) -* `#6228 `_ removed unnecessary exception from repository (gondo) * `#6212 `_ Typo in default session save_path (DerekRoth) * `#6208 `_ Replace references of PSR-0 with PSR-4 (opdavies) -* `#6170 `_ change translation getMessages() to getCatalogue() (snoek09) -* `#6211 `_ Remove 2.3.\* from composer snippets in the form component doc (Nicofuma) -* `#6225 `_ [Reference][Forms] add versionadded directive for range type (xabbuh) * `#6190 `_ Fix redundant command line sample (sylozof) @@ -185,10 +127,7 @@ January, 2016 New Documentation ~~~~~~~~~~~~~~~~~ -* `#6174 `_ Missing reference docs for kernel.finish_request event (acrobat) * `#6184 `_ added Javier as a merger for the WebProfiler bundle (fabpot) -* `#6136 `_ Update directory permissions to make var/ writable (andrerom) -* `#5600 `_ [DependencyInjection] Documented the ability of define the service decoration priority (dosten) * `#5303 `_ [WIP] 4373 - document security events (kevintweber) * `#6023 `_ clarify the routing component documentation a bit (dbu) * `#6091 `_ Added an example for info() method (javiereguiluz) @@ -197,57 +136,30 @@ Fixed Documentation ~~~~~~~~~~~~~~~~~~~ * `#6193 `_ Added the missing namespace in example of a subscriber class (raulconti) -* `#6152 `_ csrf_token_generator and csrf_token_id documentation (Raistlfiren, Aaron Valandra, xabbuh) -* `#6115 `_ [Form] Fix syntax error in code snippet (valisj) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* `#6199 `_ fix types (garak) -* `#6207 `_ revert form login CSRF changes on wrong branch (xabbuh) * `#6191 `_ Document the invalidate_session option (javiereguiluz) -* `#6204 `_ Expected: semicolon (cn007b) * `#6141 `_ Docs do not match functionality (Loupax) * `#6192 `_ fix MongoDB shell syntax highlighting (xabbuh) -* `#6147 `_ Update templating.rst - Asset absolute url fix (gbalcewicz) * `#6187 `_ Typofix for "Defining and Processing Configuration Values" (kix) -* `#6182 `_ Latest demo has no bin folder (Jace25) * `#6183 `_ use valid XML in code block (xabbuh) * `#6180 `_ use single quotes for YAML strings (snoek09) * `#6070 `_ Typo in When Things Get More Advanced (BallisticPain) * `#6119 `_ Remove phrase "in order" (micheal) -* `#6160 `_ remove versionadded for unmaintained versions (xabbuh) * `#6161 `_ [Contributing][Documentation] replace EOL with EOM (xabbuh) -* `#6166 `_ Fix by_reference deprecated FormType::class (nemo-) -* `#6162 `_ [Reference] add missing version number (xabbuh) * `#6163 `_ Remove excessive pluses (aivus) -* `#6082 `_ change app/check.php for 3.0 (nanocom) -* `#6149 `_ Reference to session + Corrected sample code char (sfdumi) -* `#6130 `_ [Security][Guard] Completed start method signature (jeremyFreeAgent) -* `#6080 `_ Removed doc about getting original parameter value from ParameterBag (edefimov) * `#6158 `_ Update override_dir_structure.rst (denniskoenigComparon) * `#6122 `_ Added missing mandatory parameter (yceruto) -* `#6108 `_ [Form] remove the getName() function as it is deprecated (aybbou) -* `#6100 `_ [Cookbook][Security] add back updateUserSecurityIdentity() hint (xabbuh) -* `#6129 `_ Added new links to the Symfony screencast series at KnpU (javiereguiluz) * `#6138 `_ Correction needed (pfleu) -* `#6139 `_ Update the doc to change a deprecated use case (ChristopheBoucaut) -* `#6133 `_ fixed the component name (fabpot) * `#6127 `_ escape namespace backslashes in class role (xabbuh) * `#5818 `_ document old way of checking validity of CSRF token (snoek09) * `#6062 `_ Update HTTP method requirement example (WouterJ) -* `#6120 `_ fix README requirements link (garak) * `#6109 `_ add link to Monolog configuration (snoek09) -* `#6121 `_ [MicroKernel] Fixed the display of a code block (jeremyFreeAgent) * `#6096 `_ [Contributing] update year in license (xabbuh) * `#6114 `_ make method protected (OskarStark) -* `#6111 `_ Fixed a typo in the choice_label code example (ferdynator) -* `#6110 `_ [Security][Guard] Fixed a typo (jeremyFreeAgent) -* `#6105 `_ Removed deprecated methods from VoterInterface (edefimov) -* `#6106 `_ Remove repetition in text (dominikhajduk) * `#6102 `_ promoted xabbuh as merger on the Yaml component (fabpot) -* `#6014 `_ [2.8][Form] entry_type option: replace "in favor" misuses (ogizanagi) -* `#6013 `_ [2.7][Form] placeholder option: replace "in favor" misuses (ogizanagi) December, 2015 @@ -256,32 +168,23 @@ December, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -* `#5906 `_ Added documentation for choice_translation_domain option (peterrehm) -* `#6017 `_ Documented the Symfony Console Styles (javiereguiluz) * `#5811 `_ Conversion from mysql to PDO (iqbalmalik89) -* `#5966 `_ Remove deprecated StringUtils from WSSE custom auth provider (pimpreneil) * `#5962 `_ Simplify code example in "Adding custom extensions" section (snoek09) -* `#5977 `_ RequestStack parameter is required since 3.0 (leunggamciu) * `#6022 `_ clarify custom route loader documentation (dbu) * `#5994 `_ Updated the release process for Symfony 3.x and future releases (javiereguiluz) -* `#5954 `_ Fix #5236 [2.8][Translation] specify additional translation loading paths (Pierre Maraitre, Balamung) -* `#5948 `_ Update 3.0 docs accordingly to min PHP version requirement (ogizanagi) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -* `#6086 `_ Update form_customization.rst (vudaltsov) * `#6063 `_ minor #5829 Fix broken composer command (JHGitty) * `#5904 `_ Update php_soap_extension.rst (xDaizu) * `#5819 `_ Remove AppBundle (roukmoute) -* `#6001 `_ Fix class name (BlueM) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `#6043 `_ Mention commiting only bower.json (krike, WouterJ) * `#5848 `_ Added hints to spool config section (martinczerwi) -* `#5586 `_ [2.8] Remove 2.6 versionaddeds as version reached eom (WouterJ) * `#6042 `_ some tweaks to unit testing form types (xabbuh) * `#6059 `_ Add best practice about the Form type namespace (WouterJ) * `#6068 `_ Remove references to API tagging (dunglas) @@ -290,29 +193,21 @@ Minor Documentation Changes * `#6094 `_ [Form] Added a missing php opening tag (dev-symfony-void) * `#5840 `_ [Contributing] [Standards] Add note about ``trigger_error()`` and deprecation messages (phansys) * `#6050 `_ Lots of minor fixes & applying best practices to form cookbook doc (ThomasLandauer, WouterJ) -* `#5993 `_ [Cookbook] [Security] Use UserLoaderInterface instead of UserProviderInterface (ogizanagi) -* `#6071 `_ Fix syntax (WouterJ) * `#5570 `_ Quick review of 'create framework' tutorial (WouterJ) * `#5445 `_ Reworded the explanation about the kernel.event_listener tag (javiereguiluz) * `#6054 `_ Remove 2.8 branch from patch documentation (Triiistan) * `#6057 `_ Fix PHP code for registering service (WouterJ) -* `#6066 `_ Update location of ``app/check.php`` to ``bin/symfony_requirements`` (Kevinrob) -* `#6067 `_ improve phrasing (greg0ire) * `#6063 `_ minor #5829 Fix broken composer command (JHGitty) * `#6041 `_ Fixed misspelling of human in glossary.rst YAML (Wasserschlange) * `#6049 `_ Finish #5798 Add ``app_`` prefix to form type names (OskarStark, WouterJ) * `#5829 `_ use composer command instead of editing json file (OskarStark) * `#6046 `_ Update framework.rst (typo in sesssion) (patrick-mota) -* `#5662 `_ Fixed wrong version of symfony with composer install (Nek-) * `#5890 `_ Updated article for modern Symfony practices and the use of bcrypt (javiereguiluz) * `#6015 `_ [Assetic] complete XML configuration examples (xabbuh) * `#5963 `_ Add note about 'phar extension' dependency (snoek09) * `#6006 `_ [Book] use AppBundle examples and follow best practices (xabbuh) * `#6016 `_ Corrected the line references for the basic controller example (theTeddyBear) * `#5446 `_ [Contributing] [Standards] Added note about phpdoc_separation (phansys) -* `#6027 `_ Update guard-authentication.rst (rvanginneken) -* `#6025 `_ Update guard-authentication.rst (rvanginneken) -* `#6038 `_ Fix #6037 (zsturgess) * `#5820 `_ Fixed an issue with command option shortcuts (javiereguiluz) * `#6033 `_ Fix Typo (Shine-neko) * `#6011 `_ Fixed formatting issues (javiereguiluz) @@ -320,24 +215,16 @@ Minor Documentation Changes * `#6009 `_ Fix missing constant usage for generating urls (Tobion) * `#5965 `_ Removing php opening tags (Deamon) * `#6003 `_ #5999 fix files names (vincentaubert) -* `#6004 `_ Fix for small typo (djoos) * `#5996 `_ Clarify example for SUBMIT form event (bkosborne) * `#6000 `_ Update registration_form.rst (afurculita) * `#5989 `_ Fix words according context (richardpq) * `#5992 `_ More use single quotes for YAML strings (snoek09) -* `#5957 `_ mark deep option as deprecated (snoek09) -* `#5940 `_ [Cookbook][ServiceContainer] move filename comment to the top of the code block (xabbuh) -* `#5943 `_ Add tip for when returning ``null`` from ``createToken()`` (jeroenseegers) -* `#5956 `_ Update security.rst (mpaquet) * `#5959 `_ Fix #5912 Ambiguity on Access Decision Manager's Strategy (Pierre Maraitre) * `#5955 `_ use single quotes for YAML strings (snoek09) * `#5979 `_ [Book] Do not extend the base controller before introducing it (ogizanagi) * `#5970 `_ Remove isSubmitted call (DanielSiepmann) * `#5972 `_ Add isSubmitted call (DanielSiepmann) -* `#5964 `_ Missing n in Column (joshuataylor) * `#5961 `_ update from_flat_php_to_symfony2.rst (thao-witkam) -* `#5924 `_ Removed note about removed content (WouterJ) -* `#5938 `_ Add proper use of the password type (themccallister) November, 2015 @@ -346,26 +233,7 @@ November, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -* `#5917 `_ [3.0][Cookbook] Use the 3.0 directory structure (WouterJ) -* `#5916 `_ [3.0][Best Practices][Quick Tour] Use the 3.0 directory structure (WouterJ) -* `#5913 `_ [3.0][Book] Use the 3.0 directory structure (WouterJ) -* `#5907 `_ Updating some places to use the new CustomUserMessageAuthenticationException (weaverryan) -* `#5922 `_ Added minimal cookbook article about the shared flag (WouterJ) -* `#5908 `_ Voter update (weaverryan) -* `#5909 `_ More 2.8 form updates (weaverryan) -* `#5927 `_ Use path() and url() PHP templating helpers (WouterJ) -* `#5926 `_ Update voter section of best practices (WouterJ) -* `#5921 `_ [2.8] Document some Security changes (WouterJ) -* `#5834 `_ Updated form aliases to FQCNs for forms in book and component (hiddewie) -* `#5265 `_ Documentation for the new Guard authentication style (weaverryan) -* `#5899 `_ Adding the MicroKernel article (weaverryan) * `#5893 `_ Added a note about the use of _format query parameter (javiereguiluz) -* `#5891 `_ Removed the comments about the is_granted() issues in non-secure pages (javiereguiluz) -* `#5876 `_ Symfony 2.7 Form choice option update (aivus, althaus, weaverryan) -* `#5861 `_ Updated Table Console helper for spanning cols and rows (hiddewie) -* `#5835 `_ Updated CssSelector code example to use the new Converter (hiddewie) -* `#5816 `_ Merge branches (nicolas-grekas, snoek09, WouterJ, xabbuh) -* `#5804 `_ Added documentation for dnsMessage option (BenjaminPaap) * `#5774 `_ Show a more real example in data collectors doc (WouterJ) * `#5735 `_ [Contributing][Code] do not distinguish regular classes and API classes (xabbuh) @@ -377,24 +245,19 @@ Fixed Documentation * `#5863 `_ Correct useAttributeAsKey usage (danrot) * `#5833 `_ Fixed whitelist delivery of swiftmailer (hiddewie) * `#5815 `_ fix constraint names (xabbuh) -* `#5793 `_ Callback Validation Constraint: Remove reference to deprecated option (ceithir) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `#5931 `_ [#5875] Fixed link description, list of common media types (Douglas Naphas) -* `#5923 `_ Remove information about request service deps of core services (WouterJ) * `#5911 `_ Wrap all strings containing @ in quotes in Yaml (WouterJ) * `#5889 `_ Always use "main" as the default firewall name (to match Symfony Standard Edition) (javiereguiluz) * `#5888 `_ Removed the use of ContainerAware class (javiereguiluz) * `#5625 `_ Tell about SYMFONY__TEMPLATING__HELPER__CODE__FILE_LINK_FORMAT (nicolas-grekas) -* `#5896 `_ [Book][Templating] Update absolute URL asset to match 2.7 (lemoinem) * `#5828 `_ move the getEntityManager, only get it if needed (OskarStark) * `#5900 `_ Added new security advisories to the docs (fabpot) * `#5897 `_ Fixed some wrong line number references in doctrine.rst (DigNative) -* `#5895 `_ Update debug_formatter.rst (strannik-06) * `#5883 `_ Book: Update Service Container Documentation (zanderbaldwin) -* `#5868 `_ [2.8] Make screenshots with the new profiler/web dev toolbar design (WouterJ) * `#5862 `_ Fixes done automatically by the docbot (WouterJ) * `#5851 `_ updated sentence (OskarStark) * `#5870 `_ Update securing_services.rst (aruku) @@ -402,21 +265,15 @@ Minor Documentation Changes * `#5866 `_ Fixed little typo with a twig example (artf) * `#5849 `_ Clarified ambiguous wording (ThomasLandauer) * `#5826 `_ "setup" is a noun or adjective, "set up" is the verb (carlos-granados) -* `#5816 `_ Merge branches (nicolas-grekas, snoek09, WouterJ, xabbuh) * `#5813 `_ use constants to choose generated URL type (xabbuh) * `#5808 `_ Reworded the explanation about flash messages (javiereguiluz) * `#5809 `_ Minor fix (javiereguiluz) -* `#5807 `_ Minor rewordings for the "deprecated" service option (javiereguiluz) * `#5805 `_ Mentioned the BETA and RC support for the Symfony Installer (javiereguiluz) * `#5781 `_ Added annotations example to Linking to Pages examples (carlos-granados) -* `#5780 `_ Clarify when we are talking about PHP and Twig (carlos-granados) * `#5767 `_ [Cookbook][Security] clarify description of the getPosition() method (xabbuh) -* `#5731 `_ [Cookbook][Security] update versionadded directive to match the content (xabbuh) * `#5681 `_ Update storage.rst (jls2933) -* `#5363 `_ Added description on how to enable the security:check command through… (bizmate) * `#5841 `_ [Cookbook][Psr7] fix zend-diactoros Packagist link (xabbuh) * `#5850 `_ Fixed typo (tobiassjosten) -* `#5852 `_ Fix doc for 2.6+, `server:start` replace `...:run` (Kevinrob) * `#5837 `_ Corrected link to ConEmu (dritter) @@ -428,15 +285,10 @@ New Documentation * `#5345 `_ Adding information about empty files sent using BinaryFileResponse. (kherge) * `#5214 `_ [WIP] Reworking most of the registration form: (weaverryan) -* `#5051 `_ Rename CollectionType entry options (WouterJ) * `#5677 `_ replacing deprecated usage of True, False, Null validators in docs (Tim Stamp) * `#5314 `_ Documented the useAttributeAsKey() method (javiereguiluz) * `#5377 `_ Added a cookbook section about event subscribers (beni0888, javiereguiluz) -* `#5623 `_ [Validator] added BIC validator (mvhirsch) -* `#5689 `_ [DI] Add some documentation for the deprecation feature (Taluu) * `#5592 `_ Updated the article about data collectors (javiereguiluz) -* `#5745 `_ [Translation] Ability to format a message catalogue without actually writing it. (aitboudad) -* `#5702 `_ Added a reference to the Foundation form theme (totophe) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ @@ -448,42 +300,30 @@ Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ * `#5843 `_ Fixed the YAML syntax for service references (javiereguiluz) -* `#5797 `_ [Process] use ProcessFailedException instead of RuntimeException. (aitboudad) -* `#5812 `_ Remove duplicate and confusing info about testing error pages (carlos-granados) * `#5821 `_ Minor fixes in the HttpFoundation introduction article (javiereguiluz) -* `#5822 `_ Fixed a syntax issue (javiereguiluz) -* `#5817 `_ fix version for `entry_options` and `entry_type` (craue) * `#5796 `_ Fix for #5783 (BenjaminPaap) * `#5810 `_ Fixed a typo (javiereguiluz) * `#5784 `_ Add fe80::1 (j-d) * `#5799 `_ make file path consitent with other articles (OskarStark) * `#5794 `_ Minor tweaks for the registration form article (javiereguiluz) * `#5801 `_ namespace fix (OskarStark) -* `#5792 `_ [Cookbook][EventDispatcher] fix build (xabbuh) * `#5787 `_ Definition Tweaks - see #5314 (weaverryan) * `#5777 `_ Update links (thewilkybarkid) * `#5775 `_ Misspelling (carlos-granados) * `#5664 `_ Info about implicit session start (ThomasLandauer) * `#5744 `_ translations have been removed from symfony.com (xabbuh) * `#5771 `_ Remove not existing response constant (amansilla) -* `#5761 `_ [DX] [Security] Renamed key to secret (SongoQ) * `#5766 `_ Fixed two typos (ThomasLandauer) -* `#5733 `_ [Components][OptionsResolver] adding type hint to normalizer callback (xabbuh) -* `#5561 `_ Change default value of cookie_httponly (jderusse) * `#5678 `_ Update HttpFoundation note after recent changes in routing component (senkal) * `#5643 `_ Document how to customize the prototype (daFish, WouterJ) -* `#5584 `_ Add DebugBundle config reference (WouterJ) -* `#5753 `_ configureOptions(...) : protected => public (lucascherifi) * `#5750 `_ fix YAML syntax highlighting (xabbuh) * `#5749 `_ complete Swiftmailer XML examples (xabbuh) -* `#5730 `_ Remove documentation of deprecated console shell (Tobion) * `#5726 `_ Document the support of Mintty for colors (stof) * `#5708 `_ Added caution to call createView after handleRequest (WouterJ) * `#5640 `_ Update controller.rst clarifying automatic deletion for flash messages (miguelvilata) * `#5578 `_ Add supported branches in platform.sh section (WouterJ) * `#5468 `_ [Cookbook][Templating] Add note about cache warming namespaced twig templates (kbond) * `#5684 `_ Fix delivery_whitelist regex (gonzalovilaseca) -* `#5742 `_ incorrect: severity is an array key here and not a constant (lbayerl) September, 2015 @@ -508,10 +348,8 @@ Fixed Documentation Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* `#5740 `_ Fix typo in PdoSessionHandler Documentation (tobemedia) * `#5719 `_ changed repo names to the new ones (fabpot) * `#5227 `_ [Cookbook] Fix doc on Generic Form Type Extensions (lemoinem) -* `#5703 `_ comment old logic (OskarStark) * `#5683 `_ Improve the demo-warning. (GuGuss) * `#5690 `_ Updated the release process image (javiereguiluz) * `#5188 `_ Updated Cookies & Caching section (lukey78) @@ -521,10 +359,8 @@ Minor Documentation Changes * `#5685 `_ Fix indentation in some annotations (iamdto) * `#5704 `_ Fix typo in translation.rst (zatikbalazs) * `#5701 `_ Update testing.rst (hansallis) -* `#5711 `_ removed service call from controller (sloba88) * `#5692 `_ Made a sentence slightly more english (GTheron) * `#5715 `_ Add missing code tag (zatikbalazs) -* `#5720 `_ adding closing tag (InfoTracer) * `#5714 `_ Remove unnecessary word from http_cache.rst (zatikbalazs) * `#5680 `_ fix grammar mistake (greg0ire) * `#5682 `_ Fix grammar and CS (iamdto) @@ -535,9 +371,6 @@ Minor Documentation Changes * `#5674 `_ Update cookbook entries with best practices (JhonnyL) * `#5675 `_ [Contributing] add a link to the testing section (xabbuh) * `#5669 `_ Better explanation of implicit exception response status code (hvt) -* `#5651 `_ [Reference][Constraints] follow best practices in the constraints reference (xabbuh) -* `#5648 `_ Minor fixes for the QuestionHelper documentation (javiereguiluz) -* `#5641 `_ Move important information out of versionadded (WouterJ) * `#5619 `_ Remove a caution note about StringUtils::equals() which is no longer true (javiereguiluz) * `#5571 `_ Some small fixes for upload files article (WouterJ) * `#5660 `_ Improved "Community Reviews" page (webmozart) @@ -558,7 +391,6 @@ Fixed Documentation ~~~~~~~~~~~~~~~~~~~ * `#5589 `_ [Cookbook][Session] fix default expiry field name (xabbuh) -* `#5607 `_ Fix (sebastianbergmann) * `#5608 `_ updated validation.rst (issei-m) * `#5449 `_ Ensure that the entity is updated. (yceruto) @@ -568,9 +400,7 @@ Minor Documentation Changes * `#5553 `_ Fix all broken links/permanent redirects/removed anchors (WouterJ) * `#5650 `_ [RFR] fixing typo and removing duplicated lines in Config component doc (salahm) * `#5635 `_ Fix minor problems in book/page_creation.rst (fabschurt) -* `#5579 `_ [3.0] Remove mentions of Symfony1 (WouterJ) * `#5647 `_ don't ignore the _exts directory anymore (xabbuh) -* `#5587 `_ [2.6] Don't use deprecated features (WouterJ) * `#5637 `_ Add QueryBuilder vs DQL section (bocharsky-bw) * `#5645 `_ Updated Constraint reference with best practices (WouterJ) * `#5646 `_ Moved comment to the right place (mickaelandrieu) @@ -588,12 +418,10 @@ Minor Documentation Changes * `#5617 `_ Add Body tag to see the web debug toolbar (rmed19) * `#5594 `_ Missing --no-interaction flag? (alexwybraniec) * `#5613 `_ Remove unneeded backtick (fabschurt) -* `#5622 `_ typo fix in pre authenticated (Maxime Douailin) * `#5624 `_ the_architecture: Fix syntax error (kainjow) * `#5609 `_ Add a missing backtick (fabschurt) * `#5312 `_ Some fixes for bundle best practices (WouterJ) * `#5601 `_ Update lazy_services.rst (baziak3) -* `#5591 `_ Update templating.rst: lint:twig instead of twig:lint in 2.7 (alexwybraniec) July, 2015 @@ -602,23 +430,16 @@ July, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -* `#5374 `_ Remove deprecated parameters (norkunas) * `#5533 `_ Replace Capifony with Capistrano/symfony (mojzis) -* `#5543 `_ Add deprecation notice to "choice_list" option of ChoiceType (XitasoChris) -* `#5521 `_ [Cookbook][WebServer] #5504 add a tip for the --force option (vincentaubert) * `#5516 `_ Added a note about session data size in PdoSessionHandler (javiereguiluz) -* `#5499 `_ The "property" option of DoctrineType was deprecated. (XWB) * `#5491 `_ added composer info (OskarStark) * `#5478 `_ Add cookbook article for using MongoDB to store session data (stevenmusumeche) * `#5472 `_ Added a tip about hashing the result of nextBytes() (javiereguiluz) -* `#5458 `_ HTML5 range documentation (harikt) * `#5453 `_ Cleanup security voters cookbook recipes (WouterJ) -* `#5444 `_ Documented the "auto_alias" feature (javiereguiluz) * `#5201 `_ [Book][Routing] Add example about how to match multiple methods (xelaris) * `#5430 `_ Pr/5085 (sjagr, javiereguiluz) * `#5456 `_ Completely re-reading the data transformers chapter (weaverryan) * `#5426 `_ Documented the checkDNS option of the Url validator (saro0h, javiereguiluz) -* `#5333 `_ [FrameworkBundle] Update serializer configuration reference (dunglas) * `#5424 `_ Integrate the "Create your own framework" tutorial (fabpot, lyrixx, jdreesen, catchamonkey, gnugat, andreia, Arnaud Kleinpeter, willdurand, amitayh, nanocom, hrbonz, Pedro Gimenez, ubick, dirkaholic, bamarni, revollat, javiereguiluz) Fixed Documentation @@ -627,7 +448,6 @@ Fixed Documentation * `#5567 `_ Change Sql Field name because it's reserved (rmed19) * `#5528 `_ [reate_framework] Fix mock $matcher (kenjis) * `#5501 `_ Fix typo in url for PHPUnit test coverage report (TrueGit) -* `#5501 `_ Fix typo in url for PHPUnit test coverage report (TrueGit) * `#5461 `_ Rework quick tour big picture (smatejic, DQNEO, xabbuh) * `#5488 `_ fix #5487 (emillosanti) * `#5496 `_ Security voters fixes (german.bortoli) @@ -640,14 +460,10 @@ Minor Documentation Changes * `#5580 `_ Additional User check in voter class (weaverryan) * `#5573 `_ fix YAML syntax highlighting (xabbuh) * `#5564 `_ Improve and simplify the contributing instructions about tests (javiereguiluz) -* `#5498 `_ [WIP] Added caution notes about the deprecation of container scopes (javiereguiluz) * `#5550 `_ [docbot] Reviewed some component chapters (WouterJ) * `#5556 `_ Fix typo Esi in part create framework (nicolasdewez) * `#5568 `_ [Create Framework] Fix extract calls (replaces #5522) (kenjis) * `#5548 `_ use the include() Twig function instead of the tag (xabbuh) -* `#5542 `_ [Cookbook][Email] add missing versionadded directive (xabbuh) -* `#5476 `_ [Cookbook][Security] some additional tweaks for the voter cookbook (xabbuh) -* `#5413 `_ Fix doc about deprecations policy (nicolas-grekas) * `#5557 `_ [2.3] [Contributing] Added note about empty returns (phansys) * `#5492 `_ updated tree for front controller (OskarStark) * `#5536 `_ Removed reference to remove HTTPS off from nginx configuration (wjzijderveld) @@ -657,27 +473,19 @@ Minor Documentation Changes * `#5490 `_ changed headline (OskarStark) * `#5479 `_ Update http-foundation.rst (jezemery) * `#5552 `_ rename $input to $greetInput (Xosofox) -* `#5544 `_ [components][expression_language] Fix the wrong constructor for SerializedParsedExpression (zerustech) * `#5537 `_ Update design patter of Event Dispatcher (almacbe) * `#5546 `_ A bunch of doc fixes again (WouterJ) * `#5486 `_ review all Security code blocks (xabbuh) -* `#5538 `_ Update email.rst (TisLars) * `#5529 `_ [Cookbook][upload_file] Fix :methods: to remove doubled braces (bicpi) * `#5455 `_ Improve travis build speed (WouterJ) * `#5442 `_ Improved the explanation about the verbosity levels of the console (javiereguiluz) -* `#5523 `_ Custom voter example, fix missing curly brace (snroki) -* `#5524 `_ TYPO: missing closing parantheses of the array (listerical85) * `#5519 `_ Prepare Platform.sh configuration files. (GuGuss) -* `#5443 `_ Added a note about the implementation of the verbosity semantic methods (javiereguiluz) * `#5518 `_ Minor grammar fix. (maxolasersquad) -* `#5520 `_ Fix RST (kenjis) -* `#5429 `_ Promote Symfony's builtin serializer instead of JMS (javiereguiluz) * `#5427 `_ Cookbook grammar and style fixes (frne, javiereguiluz) * `#5505 `_ [Cookbook][Form] some tweaks to the data transformers chapter (xabbuh) * `#5352 `_ Update http_fundamentals.rst (wouthoekstra) * `#5471 `_ Updated the Symfony Versions Roadmap image (javiereguiluz) * `#5511 `_ [HttpKernel] Fix use statement (dunglas) -* `#5510 `_ [PSR-7] Fix Diactoros link (dunglas) * `#5506 `_ Fixes small typo in data transformers cookbook (catchamonkey) * `#5425 `_ Added a caution note about invoking other commands (kix, javiereguiluz) * `#5367 `_ Split Security into Authentication & Authorization (iltar) @@ -692,22 +500,14 @@ June, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -* `#5423 `_ [Security] add & update doc entries on AbstractVoter implementation (Inoryy, javiereguiluz) -* `#5409 `_ [Reference] document new Doctrine APC cache service (xabbuh) * `#5401 `_ Added some more docs about the remember me feature (WouterJ) -* `#5384 `_ Added information about the new date handling in the comparison constraints and Range (webmozart, javiereguiluz) * `#5382 `_ Added support for standard Forwarded header (tony-co, javiereguiluz) * `#5361 `_ Document security.switch_user event (Rvanlaak) -* `#5332 `_ [Serializer] ObjectNormalizer, object_to_populate doc. Minor enhancements. (dunglas) -* `#5335 `_ [Serializer] Updated the cookbook. (dunglas) * `#5313 `_ Documented the overridden form options (javiereguiluz) -* `#5360 `_ [Serializer] Array Denormalization (derrabus) * `#5307 `_ Update data_transformers.rst (zebba) * `#5186 `_ Added a new article about using/installing unstable Symfony versions (javiereguiluz) * `#5166 `_ Proposed a new article about using pure PHP libraries with Assetic (javiereguiluz) -* `#5416 `_ fix for Symfony 2.7 (DQNEO) * `#5014 `_ Updated the best practices article for reusable bundles (javiereguiluz) -* `#5435 `_ Added information about the four sub-components of Security component (javiereguiluz) * `#5368 `_ added examples for squashing (OskarStark) * `#5428 `_ Improved description of choice_list option (adamziel, javiereguiluz) * `#5336 `_ Adding a paragraph about updating multiple packages during an update (weaverryan) @@ -715,28 +515,20 @@ New Documentation * `#5385 `_ Added a note about the need to require Composer's autoload file (javiereguiluz) * `#5386 `_ Re-write of Page Creation (weaverryan) * `#5355 `_ Added a mention to the Symfony Demo application (javiereguiluz) -* `#5331 `_ [PSR-7] Bridge documentation (dunglas) * `#5373 `_ Added mentions to some popular (and useful) Symfony bundles (javiereguiluz) -* `#4354 `_ [WCM] Added depreciation note for the cascade_validation constraint (peterrehm) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -* `#5415 `_ Updating for AppBundle and purposefully \*not\* doing work on configure (weaverryan) * `#5407 `_ Change PhpStormOpener to PhpStormProtocol (King2500) -* `#5450 `_ Fixing "Undefined method" error in code example (nebkam) * `#5454 `_ Changed dump() to var_dump() (WouterJ) * `#5417 `_ Add use statement for InputDefinition (harikt) * `#5420 `_ Fix invalid method name (bocharsky-bw) * `#5431 `_ Updated the code to display flash messages (aykin, javiereguiluz) -* `#5418 `_ Import Psr LogLevel (harikt) * `#5438 `_ Fixed 404 at Configuring Sessions and Save Handlers (2.3 branch) (suzuki) -* `#5412 `_ Update serializer.rst (mantulo) * `#5397 `_ Escape backslash in error message (WouterJ) * `#5379 `_ [Cookbook][Console] don't use BufferedOutput on Symfony 2.3 (xabbuh) -* `#5400 `_ Fix after install URL and new photo since AcmeDemoBundle is not part … (smatejic) * `#5350 `_ [Form][2.3] fix `validation_groups` typos (craue) -* `#5358 `_ Fix typo in description (martyshka) * `#5356 `_ [Form] Fixed typo about _token field name for CSRF protection (JMLamodiere) * `#5362 `_ Fix invalid endtag (norkunas) @@ -748,12 +540,10 @@ Minor Documentation Changes * `#5414 `_ Rewrite sentence about fingers crossed handler action level (snoek09) * `#5402 `_ [Contributing] [Standards] Added entry for Yoda conditions (phansys) * `#5369 `_ Remove the Propel book chapter and explain why we do that (javiereguiluz) -* `#5460 `_ Finish #5291: Bootstrap form theme and checkboxes (anacicconi, WouterJ) * `#5457 `_ [Cookbook][Assetic] complete a sentence (xabbuh) * `#5398 `_ Quick review of the remember me article (WouterJ) * `#5399 `_ Quick review of Form login chapter (WouterJ) * `#5403 `_ [Contributing] [Standards] Added entry for identical comparison (phansys) -* `#5392 `_ Wrap the table creation inside the class extending Command, so users … (harikt) * `#5378 `_ [Cookbook][Controller] use the jinja lexer to render Twig code (xabbuh) * `#5421 `_ Update the name of the branch for new BC features (Restless-ET) * `#5441 `_ [Contributing] remove mailing list and forum references (xabbuh) @@ -762,9 +552,7 @@ Minor Documentation Changes * `#5290 `_ Overriding 3rd party bundles (anacicconi) * `#5242 `_ Update load_balancer_reverse_proxy.rst (urg) * `#5381 `_ remove Yoda condition (greg0ire) -* `#5452 `_ [#5388] change echo and print in examples (snoek09) * `#5451 `_ [#5388] change echo and print in examples (snoek09) -* `#3782 `_ [Form] Deprecate read_only option (snoob) * `#5432 `_ removed squashing stuff. fixes #5368 (OskarStark) * `#5383 `_ Reword a paragraph about service configurations (richardudovich) * `#5389 `_ Updates to security.rst (HexTitan) @@ -774,9 +562,7 @@ Minor Documentation Changes * `#5288 `_ Constraints - empty strings and null values (anacicconi) * `#5284 `_ Split advanced container configuration article (WouterJ) * `#5342 `_ [Cookbook][Bundles] clarify bundle installation instructions (xabbuh) -* `#5321 `_ Use the reserved domains example.com and example.org (javiereguiluz) * `#5095 `_ Reviewed the Bundles cookbook articles (javiereguiluz) -* `#4947 `_ [Components][ClassLoader] remove DebugClassLoader (xabbuh) * `#5365 `_ Finish #4967: Code style standardization on form type options (mimol91) * `#5034 `_ Update the_big_picture.rst (oldskool) * `#5351 `_ [Finder] minor CS fix (dunglas) @@ -792,54 +578,39 @@ May, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -* `#5329 `_ Adding a new entry about deprecation warnings (weaverryan) * `#4604 `_ Making the channel handler more useful by showing it on the prod environment (weaverryan) * `#5155 `_ Documented upgrading path for a major version (WouterJ) -* `#5127 `_ [VarDumper] Add doc for assertDump\* assertions (nicolas-grekas) * `#5137 `_ Added a note about the rotating_file monolog handler (javiereguiluz) * `#5283 `_ [BestPractices] restructured text format for the installation instructions template (xabbuh) * `#5298 `_ Completed framework config (WouterJ) -* `#5255 `_ [Cookbook] Use configured user provider instead of injection (mvar) * `#5216 `_ [Cookbook] [Deployment] Added note about Nginx (phansys) -* `#5169 `_ Removed synchronized services from Symfony 2.7 docs (javiereguiluz) * `#5117 `_ Complete review of the "Customize Error Pages" cookbook article (javiereguiluz) * `#5115 `_ Flesh out twig-template for custom data-collector (Darien Hager) -* `#5106 `_ [VarDumper] upgrade doc to 2.7 wither interface (nicolas-grekas) * `#4728 `_ Add Session Cache Limiting section for NativeSessionStorage (mrclay) -* `#4084 `_ [Book][Forms] describe the allow_extra_fields form option (xabbuh) * `#5294 `_ Tweaks to bower entry - specifically committing deps (weaverryan) * `#5062 `_ Cookbook about Command in Application with AnsiToHtml (Rvanlaak) * `#4901 `_ Removed the Internals chapter from the Symfony book (javiereguiluz) -* `#4807 `_ [2.7] bumped min PHP version to 5.3.9 (xelaris) * `#4790 `_ [Cookbook][Routing] Update custom_route_loader.rst (xelaris) * `#5159 `_ Added an article explaining how to use Bower in Symfony (WouterJ) * `#4700 `_ add informations how to create a custom doctrine mapping (timglabisch) -* `#4675 `_ [Serializer] Doc for groups support (dunglas) * `#5164 `_ Added information about the Symfony Demo application (javiereguiluz) * `#5100 `_ Change MySQL UTF-8 examples to use utf8mb4 (DHager, Darien Hager) * `#5088 `_ [Cookbook] Custom compile steps on Heroku (bicpi) -* `#5005 `_ Renamed precision option to scale (WouterJ) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ * `#5324 `_ 5259 improve 'Testing Documentation' in contributing guide (snoek09) -* `#5328 `_ Update create_form_type_extension.rst (jackdelin) -* `#5305 `_ [BestPractices][Security] revert #5271 on the 2.6 branch (xabbuh) * `#5251 `_ [Cookbook][Controller] replace docs for removed `forward()` method (xabbuh) -* `#5237 `_ Update authentication.rst (taavit) * `#5299 `_ Command controller tweaks to #5062 (weaverryan) * `#5297 `_ Kernel Events Proofreading after #4901 (weaverryan) * `#5296 `_ Fix link to Zend Soap (peterkokot) * `#5266 `_ Update heroku.rst (nickbyfleet) -* `#5270 `_ Use OptionsResolver (tacman) * `#5271 `_ Fix nonexistent controller method (amansilla) * `#4615 `_ Update NotBlank to reflect the actual validation (DRvanR) * `#5249 `_ [security][form login] fix translations for the security messages. (aitboudad) -* `#5247 `_ [2.7] [Serializer] fixes the order of the Serializer constructor arguments. (hhamon) * `#5220 `_ Fix example namespace (lepiaf) * `#5203 `_ Order has one param without spaces (carlosbuenosvinos) -* `#4273 `_ - fix doctrine version in How to Provide Model Classes for several Doctrine Implementations cookbook Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -852,7 +623,6 @@ Minor Documentation Changes * `#5338 `_ Text in index.html.twig for The Big Picture wrong (BT643) * `#5341 `_ fixed typo and added additional hit for NullOutput() (kuldipem) * `#5302 `_ Place DQL in front of QueryBuilder (alfonsomga) -* `#5276 `_ Better illustrate what the "user mistake" is. (diamondsea) * `#5304 `_ Proofreading Javier's excellent updates - in some places, shortening some things (weaverryan) * `#5263 `_ Let docbot review the form docs (WouterJ) * `#5280 `_ Rebase #4633 (seangallavan) @@ -865,16 +635,13 @@ Minor Documentation Changes * `#5277 `_ always refer to getcomposer.org through HTTPS (xabbuh) * `#4671 `_ consistent spelling (xabbuh) * `#4255 `_ Updated autoload standard to PSR-4. (phansys) -* `#5278 `_ remove unnecessary code (karion) * `#5262 `_ Update Routes in the Getting Started documentation (BT643) -* `#5178 `_ Usage of denyAccessUnlessGranted in the controller (94noni) * `#5229 `_ Remove mention of \*.class parameters from conventions (jvasseur) * `#5250 `_ [Cookbook][Logging] use straightforward instead of straigt forward (xabbuh) * `#5257 `_ Let docbot review the constraint docs (WouterJ) * `#5222 `_ Update service_container.rst (assoum891) * `#5221 `_ Update Uglifyjs.rst (assoum891) * `#5219 `_ Fix contradicting merging policy rules (lscholten) -* `#5217 `_ Update _payload-option.rst.inc (bvleur) * `#5226 `_ Update http_cache.rst (assoum891) * `#5238 `_ Fixed typo and removed outdated imports (nomack84) * `#5240 `_ [Cookbook][Email] revert #4808 (xabbuh) @@ -888,12 +655,10 @@ New Documentation - `387ebc0 `_ #5109 Improved the explanation about the "secret" configuration parameter (javiereguiluz) - `cac0a9c `_ #5207 Updated the cookbook about Composer installation (javiereguiluz) -- `b5dd5a1 `_ #5206 [Cookbook][Security] Replace deprecated csrf_provider service (xelaris) - `99e2034 `_ #5195 Add missing caching drivers (mhor) - `b90c7cb `_ #5078 [Cookbook] Add warning about Composer dev deps on Heroku (bicpi) - `55730c4 `_ #5021 Explained the "Remember Me" firewall options (javiereguiluz) - `45ba71b `_ #4811 Simplified some Symfony installation instructions (javiereguiluz) -- `c4a5661 `_ #5060 Adds note on new validation files scanned in 2.7 (GromNaN) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ @@ -902,19 +667,14 @@ Fixed Documentation - `49f6b2a `_ #5211 Rebase #5182 (Balamung) - `318bb8a `_ #5187 Fixing a bad bcrypt string using http://www.bcrypt-generator.com/ (weaverryan) - `6fb2eea `_ #5162 Fix misplelled XliffFileLoader class in the Using Domains (Nicola Pietroluongo) -- `402b586 `_ #5162 Fix misplelled XliffFileLoader class in the Using Message Domains (Nicola Pietroluongo) - `8fc3d6c `_ #5149 Fixed loadUserByUsername method coding errors (Linas Merkevicius) - `2a1d2bb `_ #5153 [Book] app_dev with php built-in web server (manelselles) - `c6e6d28 `_ #5061 Trim default is false in password field (raziel057) -- `5880f38 `_ #5126 Fix a typo in ProgressBar usage example (kamazee) - `65c1669 `_ #5124 #3412 correct overridden option name of timezone (alexandr-kalenyuk) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `0b7f89b `_ #4868 Remove horizontal scrollbar (ifdattic) -- `c166fdf `_ #5212 Fixed typo. (pcky) -- `134268e `_ #5209 [Reference] Fix order of config blocks (xelaris) - `c6dc4ea `_ #5200 Added missing link in "Sections" (sfdumi) - `8b25e6e `_ #5198 Link twig constant function (davidfuhr) - `2d6d78c `_ #5194 Fix priority range values for event listeners. (chtipepere) @@ -932,7 +692,6 @@ Minor Documentation Changes - `d9e1690 `_ #5096 Reviewed Cache cookbook articles (javiereguiluz) - `c40b618 `_ #5065 [Reference] fix code block order (xabbuh) - `73ccc8b `_ #5160 Update process.rst (sfdumi) -- `ab01d08 `_ #5141 Removed remaining setDefaultOptions usage (WouterJ) - `0dc6204 `_ #5143 Rebased #4747 (ifdattic) - `b467e23 `_ #5147 Add missing word in bundles best practice description (jbafford) - `bf1e44b `_ #5150 [Cookbook] Update serializer.rst (xelaris) @@ -940,10 +699,7 @@ Minor Documentation Changes - `b73346a `_ #5145 Update introduction.rst (cafferata) - `7f39e87 `_ #5073 [Cookbook] Add note about possible 404 error on Heroku (bicpi) - `fbdc177 `_ #5057 Add a link to Multiple User Providers (thePanz) -- `526c880 `_ #5132 [Components][DependencyInjection] fix wrong disable of factories (sstok) - `b19ded6 `_ #5130 [Cookbook][Security] Fiyed typo in entity_provider.rst (althaus) -- `87c39b7 `_ #5129 Fix to Twig asset function packageName argument (ockcyp) -- `1d443c0 `_ #5128 [VarDumper] little optim (lyrixx) March, 2015 ----------- @@ -951,45 +707,31 @@ March, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -- `25d2f54 `_ #4958 Add Twitter Bootstrap form theme example (bocharsky-bw) - `8ac6fed `_ #5093 Added a new best practices for custom form field types (javiereguiluz) - `50cd620 `_ #4892 Add possible values for widget_type (XitasoChris) - `ade7ba4 `_ #4842 Add meaning of yellow icon for number of queries (XitasoChris) - `fa10f1c `_ #5083 Proofreading and updating entity_provider for readability (weaverryan) - `e36faec `_ #5099 Rebase of #4989 (solazs, weaverryan) - `65dd03b `_ #5056 [Reference] Add missing option delivery_whitelist (TerjeBr) -- `c2f21e6 `_ #5050 [OptionsResolver] Fixed deprecated functionality usage (WouterJ) -- `3405c42 `_ #5046 Rebased "add shortcut methods" (Cydonia7, WouterJ) - `b138a50 `_ #5032 Minor improvement for symfony-installer with LTS (94noni) - `5261e79 `_ #5033 adding table for controller as a service (dbu) -- `d6c0cb7 `_ #5028 Finish #4308: Documentation for the new PropertyNormalizer (mnapoli, WouterJ) - `ccabc95 `_ #5023 Added a note about data transformers not being applied with inherit_data option set (javiereguiluz) - `65a33c0 `_ #5020 Added a commented config useful when you use symlinks (javiereguiluz) - `1dbed80 `_ #5017 Added a note about the server_version DBAL option (javiereguiluz) - `86abdde `_ #5015 Added an example about how to get the impersonating user object (javiereguiluz) - `c6db525 `_ #5010 Added a note about the Symfony versions affected by ICU problems (javiereguiluz) - `3c76623 `_ #5008 Added a note about how to enable http_method_override for caching kernels (javiereguiluz) -- `22eee86 `_ #4987 Added the documentation for the new Asset component (javiereguiluz) -- `3fb19ce `_ #4959 Add excluded_ajax_paths new parameter in v2.6 (bocharsky-bw) -- `78733c3 `_ #4941 Adding a section to emailing showing off absolute_url (weaverryan) -- `325354e `_ #4903 Reworded the explanation about when a lock is released (javiereguiluz) - `d76f046 `_ #4875 Added chapter about the locale based on the user entity (peterrehm) - `0d1e97e `_ #4834 [translator] use the new fallbacks option. (aitboudad) - `9846d97 `_ #5001 Best practices template names (WouterJ) - `8e93786 `_ #4779 Update book to comply with best practices, round 3 (WouterJ) -- `dbdb408 `_ #4724 [Reference][Constraints] document the validation payload option (xabbuh) -- `f8e2e19 `_ #4692 [Serializer] Name Converter (dunglas) - `24c4f42 `_ #4732 [Reference] add missing reference options and descriptions (xabbuh) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ - `6ba6ffd `_ #5058 Fix: assets_version instead of asset_version (sebastianblum) -- `edf9b78 `_ #5118 Update logger.rst (jdecoster) -- `adf5b90 `_ #5110 [Serializer] Fix class name (iamluc) -- `d65880f `_ #5092 Fixed a minor error introduced by the new redirectToRoute() method (javiereguiluz) - `206e613 `_ #4304 [DX] Suggest a hint to any auth-check (larsborn) -- `df9c3f4 `_ #5053 Correct RegisterListenersPass namespace (hacfi) - `893ffad `_ #5041 Fixed variable name in : Reference -> validation constraints -> count -> PHP (aminemat) - `42ba278 `_ #5037 Finish 4644: Update the_controller.rst (teggen, WouterJ) - `e9b9376 `_ #5009 Reworded the explanation about optional command options (javiereguiluz) @@ -1009,19 +751,16 @@ Minor Documentation Changes - `6b96470 `_ #5076 Better explain that form types should be unique in the application (javiereguiluz) - `cdb9350 `_ #5086 Use AppBundle instead of AcmeDemoBundle for consistency (snamor) - `6719802 `_ #5108 [Components][HttpKernel] fix typo in event flow diagrams (xabbuh) -- `d6a838a `_ #5082 Proofreading tweaks to asset component (weaverryan) - `17a6863 `_ #5094 Reviewed the Assetic cookbook articles (javiereguiluz) - `ac9ba97 `_ #4909 Remove horizontal scrollbar and other fixes (ifdattic) - `51af15d `_ #5087 added Abdellatif as a core team member (fabpot) - `a801d57 `_ #4601 [Heroku] A few more tweaks to outline the steps (weaverryan) - `b76ffad `_ #4464 [BestPractices Removing micro-optimization note about @Template (weaverryan) - `b3e204c `_ #5079 [Contributing][Code] link to deciders' GitHub profiles (xabbuh) -- `33232a8 `_ #5075 Removed an admonition that is no longer true for Symfony 2.6+ (javiereguiluz) - `4307190 `_ #5072 Add missing use statement in Building Login Form doc (ockcyp) - `9468b9a `_ #5071 Fixed incorrect plural form (Katharina Störmer) - `63f1ca3 `_ #5066 [Reference] enclose data type with double backticks (xabbuh) - `dc01076 `_ #5064 Updated documentation standards (code examples and English use) (javiereguiluz) -- `0d0c795 `_ #5047 Fix service id (JhonnyL) - `2fe8f76 `_ #5044 Minor improvement in the node types explanation (javiereguiluz) - `9b1f5f1 `_ #5043 Switched the first example to a static constructor method (kix) - `ce19196 `_ #5042 added some more components for Tobion as a merger (fabpot) @@ -1038,7 +777,6 @@ Minor Documentation Changes - `3be0081 `_ #4976 Improved sentence (edsonmedina) - `a444220 `_ #4885 Fix typos (ifdattic) - `482502d `_ #4793 [Contributing] Several tweaks (xelaris) -- `a2395ef `_ #5054 [Changelog] fix changelog syntax (xabbuh) - `6b66f03 `_ #5003 Updated the generic Deployment article (javiereguiluz) - `39a1487 `_ #4999 Fixed semantic error (beni0888) @@ -1048,41 +786,29 @@ February, 2015 New Documentation ~~~~~~~~~~~~~~~~~ -- `16dcf53 `_ #4980 [#4974] Added Twig loader priority Documentation (wizhippo) - `a25da10 `_ #4966 [#4231] Clarify that only the main command triggers events (riperez) -- `c6bea37 `_ #4957 Added a mention to the @Security annotation (javiereguiluz) - `9cce63c `_ #4924 [swiftmailer] Document whitelist option to email redirect (TerjeBr) -- `14a080f `_ #4907 Adjustments to PDO Session storage page (kbond) - `f5ff45e `_ #4712 Provide full test example (ifdattic) - `5e83045 `_ #4657 Update assetic watch command (xtreamwayz) - `d447b12 `_ #4556 Updated twig reference with optimizations and paths (jzawadzki) -- `ed80100 `_ minor #4977 Unnecessary comma (edsonmedina) - `018cf3f `_ #4661 Added a short cookbook about avoiding the automatic start of the sessions (javiereguiluz) - `2305066 `_ #4902 Removed the Stable API chapter from the Symfony book (javiereguiluz) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `215cacf `_ #4423 Fix description of ConfirmationQuestion (cxj) -- `ed80100 `_ minor #4977 Unnecessary comma (edsonmedina) -- `583ec92 `_ #4984 Fix the example using SerializedParsedExpression (stof) - `b0d9c5c `_ #4978 fix wrong header-line syntax (sstok) - `6d65564 `_ #4954 Fixed some syntax issues in Twig Reference (javiereguiluz) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `2a29225 `_ #4985 Fixed a typo (javiereguiluz) - `f75bc2b `_ #4972 Fix typos (ifdattic) -- `89e626f `_ #4952 symfony 2.7 requires at least php 5.3.9 (scaytrase) - `9fab10b `_ #4854 Removed no longer needed information about PHP 5.3 (WouterJ) - `1726054 `_ #4500 Link to standard edition (harikt) - `91ff6f8 `_ #4329 ensure consistency with the note (greg0ire) -- `f4ab4b6 `_ #5002 Revert very bad merge (WouterJ) - `e5dbd49 `_ #4977 Unnecessary comma (edsonmedina) -- `ed80100 `_ #4977 Unnecessary comma (edsonmedina) - `5d44987 `_ #4991 Fixed typo and tweaked syntax. (cdvrooman) -- `b1aadbf `_ #4993 Bumped symfony version number to 2.6 in flat php composer.json example (TSchuermans) - `3845c9c `_ #4979 require_once path fixed (mvanmeerbeck) - `96770aa `_ #4969 Add typehint (piotrantosik) - `f97d01f `_ #4995 [#4965] file extension fix (hansstevens) @@ -1094,9 +820,7 @@ Minor Documentation Changes - `0a85053 `_ #4950 Fixes for 2.3 branch (ifdattic) - `d3d96e1 `_ #4951 fix characters in backported patch (xabbuh) - `208904a `_ #4949 Fixes for 2.3 branch (ifdattic) -- `6be214c `_ #4948 Fixes for 2.6 branch (ifdattic) - `42b44c4 `_ #4929 Remove block which doesn't make sense after best practices (ifdattic) -- `008c4de `_ #4928 Change installation method order (ifdattic) - `6f8b145 `_ #4904 Added a reference about including JS and CSS files in PHP templates (javiereguiluz) January, 2015 @@ -1107,27 +831,17 @@ New Documentation - `b32accb `_ minor #4935 Fix typos (ifdattic) - `ad74169 `_ #4628 Varnish cookbook session cookie handling (dbu) -- `50c5a9e `_ #4895 Added configuration of the user provider (peterrehm) -- `4226fc2 `_ #4883 Global dump (nicolas-grekas) -- `a57db5b `_ #4879 Documented true regex (WouterJ) - `3bb7b61 `_ #4645 Remove note that's no longer the case (thewilkybarkid) - `3293286 `_ #4801 [Cookbook][cache][varnish] be more precise about version differences (dbu) -- `572bf3b `_ #4800 [Cookbook][Security] Hint about createToken can return null (xelaris) -- `74d2e30 `_ #4786 Replaced setDefaultOptions by the new configureOptions method (peterrehm) - `528e8e1 `_ #4740 Use AppBundle whenever it's possible (javiereguiluz) -- `08e5ac9 `_ #4658 Debug formatter tweaks (weaverryan) -- `cfad26c `_ #4605 Adding a link to log things in the prod environment (weaverryan) -- `3643ec2 `_ #4723 [Cookbook][Security] document the new AuthenticationUtils (xabbuh) - `9742b92 `_ #4761 [Cookbook][Security] don't output message from AuthenticationException (xabbuh) - `a23e7d2 `_ #4643 How to override vendor directory location (gajdaw) - `99aca45 `_ #4749 [2.3][Book][Security] Add isPasswordValid doc as in 2.6 (xelaris) - `d9935a3 `_ #4141 Notes about caching pages with a CSRF Form (ricardclau) - `207f2f0 `_ #4711 [Reference] Add default_locale config description (xelaris) - `1b0fe77 `_ #4708 Change Apache php-fpm proxy configuration (TeLiXj) -- `7be0dc6 `_ #4681 adding note to assetic cache busting (weaverryan) - `127ebc1 `_ #4650 Documented the characters that provoke a YAML escaping string (javiereguiluz) - `0c0b708 `_ #4454 More concrete explanation of validation groups (peterrehm) -- `4fe4f65 `_ #4682 [Reference] document the `````2.5````` validation options (xabbuh) - `144e5af `_ #4611 Adding a guide about upgrading (weaverryan) - `01df3e7 `_ #4626 clean up cache invalidation information on the cache chapter (dbu) - `5f7ef85 `_ #4651 Documented the security:check command (javiereguiluz) @@ -1139,15 +853,11 @@ Fixed Documentation - `b32accb `_ minor #4935 Fix typos (ifdattic) - `7e84533 `_ #4886 [Best Pracitices] restore example in the "Service: No Class Parameter" section (u-voelkel) - `a6b7d72 `_ #4861 Ifdattic's fixes (ifdattic) -- `8ef3477 `_ #4856 [Components][Debug] fix DebugClassLoader namespace (xabbuh) - `b9359a2 `_ #4905 Update routing.rst (IlhamiD) - `9fee9ee `_ #4746 Revert #4651 for 2.3 branch (xelaris) - `5940d52 `_ #4735 [BestPractices] remove @Security annotation for Symfony 2.3 (xabbuh) -- `ce37b96 `_ #4771 [QuickTour] use the debug:router command name (xabbuh) - `ffe3425 `_ #4765 [Book][Forms] avoid the request service where possible (xabbuh) -- `36f2e1f `_ #4757 [Components][ClassLoader] don't show deprecated usage of ``Yaml::parse()`` (xabbuh) - `d8e8d75 `_ #4756 [Components][Config] don't show deprecated usage of ``Yaml::parse()`` (xabbuh) -- `b143754 `_ #4744 [Book][Security] Update code example to fit description (xelaris) - `310f4ae `_ #4639 Update by_reference.rst.inc (docteurklein) Minor Documentation Changes @@ -1158,17 +868,11 @@ Minor Documentation Changes - `c24c787 `_ #4931 Remove horizontal scrollbar (ifdattic) - `83696b8 `_ #4934 Fixes for 2.3 branch (ifdattic) - `99d225b `_ #4943 Fixes for 2.3 branch (ifdattic) -- `3907af6 `_ #4944 Fix formatting (ifdattic) - `137ba72 `_ #4945 Fixes for 2.3 branch (ifdattic) -- `5a53e87 `_ #4946 Remove horizontal scrollbar (ifdattic) - `b32accb `_ #4935 Fix typos (ifdattic) -- `04090c0 `_ #4936 fixed typo (issei-m) - `0fa9cbd `_ #4937 Keeping documentation consistent (thecatontheflat) - `3921d70 `_ #4918 Quick proofread of the email cookbook (weaverryan) -- `768650e `_ #4932 Add missing comma in array (ifdattic) - `418a73b `_ #4922 Fix typo: missing space (ifdattic) -- `30ecdde `_ #4921 Fixes for 2.5 branch (ifdattic) -- `d1103a8 `_ #4919 Fix code examples (ifdattic) - `20d80c3 `_ #4916 Fixes for 2.3 branch (ifdattic) - `d7acccf `_ #4914 Fix typo, remove horizontal scrollbar (ifdattic) - `fc776ab `_ #4894 Align methods in YAML example (ifdattic) @@ -1180,53 +884,35 @@ Minor Documentation Changes - `00981de `_ #4890 Fixed typo (beni0888) - `dc87147 `_ #4876 Remove horizontal scrollbar (ifdattic) - `f5f3c1b `_ #4865 Removed literals for bundle names (WouterJ) -- `33914c9 `_ #4859 [Components][EventDispatcher] don't explain deprecated `````getName()````` method (xabbuh) - `9a6d7b9 `_ #4831 Update override.rst (ifdattic) - `f9c2d69 `_ #4803 [Book][Translation] Added tip for routing params (xelaris) -- `2f41c9e `_ #4887 Typo (XitasoChris) - `3774a37 `_ #4881 Remove 'acme' (ifdattic) -- `d85fa76 `_ #4880 Remove duplicate link, introduction.rst (Quberik) - `6a15077 `_ #4874 Remove trailing whitespace (WouterJ) - `80bef5a `_ #4873 [BestPractices] fix typo (xabbuh) - `6cffa4e `_ #4866 Remove horizontal scrollbar (ifdattic) -- `65b0822 `_ #4798 Add version added note for the debug:event-dispatcher command (adamelso) - `bcf1508 `_ #4785 [Book][Security] add back old anchors (xabbuh) -- `4143076 `_ #4872 [BestPractices] fix merge after removing @Security in 2.3 (xabbuh) -- `dc25c65 `_ #4769 [2.7] Removed 2.5 versionadded as its deprecated (WouterJ) -- `48835de `_ #4767 [2.6] Removed 2.4 versionadded as version is deprecated (WouterJ) -- `240a981 `_ #4764 [Reference][Forms] move cautions to make them visible (xabbuh) - `cf3d38a `_ #4731 [Book][Testing] bump required PHPUnit version (xabbuh) - `4f47dec `_ #4837 Monolog Cookbook Typo Fix: "allows to" should be "allows you to" (mattjanssen) - `c454fd2 `_ #4857 Add custom link labels where Cookbook articles titles looked wrong (javiereguiluz) - `17989fd `_ #4860 [Components][HttpKernel] replace API link for SwiftmailerBundle (xabbuh) -- `84839ba `_ #4829 Fix code example (ifdattic) - `e347ec8 `_ #4819 Removed a leftover comma in security config sample (javiereguiluz) - `11b9d23 `_ #4772 Tweaks to the new form csrf caching entry (weaverryan) -- `c04ed79 `_ #4848 Fix typo: BLOG => BLOB (ifdattic) - `f9c1389 `_ #4845 Update security.rst (meelijane) - `9680ec0 `_ #4844 Update routing.rst (bglamer) - `c243d00 `_ #4843 Fixed typo (beni0888) -- `5b91653 `_ #4843 Fixed typo (beni0888) - `13ffb83 `_ #4835 Fixed broken link (SofHad) - `d2a67ac `_ #4826 Fixed 404 page (SofHad) - `f34fc2d `_ #4825 Fixed the 404 not found error (SofHad) -- `467c538 `_ #4824 fix SQL: table names (e-moe) - `91a89b7 `_ #4821 Fixed typo (SofHad) - `f7179df `_ #4818 [Routing] Removed deprecated usage (WouterJ) -- `82bce29 `_ #4815 Update translation.rst (ifdattic) - `892586b `_ #4808 Email message instantiation changed to a more 'symfonysh' way. (alebo) - `e913808 `_ #4802 [Cookbook][Routing] Fixed typo (xelaris) -- `6522145 `_ #4799 Fix markup (WouterJ) -- `a42e5b6 `_ #4778 Update templating.rst (ifdattic) -- `bd7d246 `_ #4752 [Book][Validation] clarify group validation (xabbuh) - `236c26f `_ #4796 Update service_container.rst (ifdattic) - `f85c44c `_ #4795 Remove horizontal scrollbar (ifdattic) - `45189bb `_ #4792 [BestPractices] add filename to codeblock (xelaris) - `fccea1d `_ #4791 Fix heading level in form_login_setup.rst (xelaris) - `74c3a35 `_ #4788 Controller is a callable (timglabisch) -- `eb56376 `_ #4781 [Serializer] Bad variable name in example (arno14) - `28571fc `_ #4780 Add missing semicolon (NightFox7) -- `32bd0b1 `_ #4777 Update templating.rst (ifdattic) - `dc5d8f8 `_ #4760 Update routing.rst (ifdattic) - `4e880c1 `_ #4755 fix typo (xabbuh) - `463c30b `_ #4751 [BestPractices] fix alignment of YAML values (xelaris) @@ -1234,7 +920,6 @@ Minor Documentation Changes - `f4f8621 `_ #4762 [Cookbook][Configuration] update text to use SetHandler (not ProxyPassMatch) (xabbuh) - `43543bb `_ #4748 Re-reading private service section (weaverryan) - `e447e70 `_ #4743 [Book][Security] Fix typo and remove redundant sentence (xelaris) -- `97a9c7b `_ #4742 Formatting fix (WouterJ) - `9819113 `_ #4702 Clarify tip for creating a new AppBundle (xelaris) - `8f2fe87 `_ #4683 [Reference] update the configuration reference (xabbuh) - `e889813 `_ #4677 Add exception to console exception log (adrienbrault) @@ -1243,13 +928,10 @@ Minor Documentation Changes - `aa9d982 `_ #4697 Set twig service as private (ifdattic) - `ece2c81 `_ #4722 Improve readability (ifdattic) - `dcc9516 `_ #4725 Remove horizontal scrollbar (ifdattic) -- `3eb14aa `_ #4727 Renamed example: "Acme\BlogBundle" -> "AppBundle" (muxator) - `25dd825 `_ #4730 Fix typo: as => is (ifdattic) - `760a441 `_ #4734 [BestPractices] add missing comma (xabbuh) -- `caa2be6 `_ #4737 [Book][Security] add missing versionadded directive (xabbuh) - `8c1afb9 `_ #4738 [Contributing][Code] update year in license (xabbuh) - `4ad72d0 `_ #4741 use the doc role for internal links (jms85, xabbuh) -- `57fdea6 `_ #4729 Fixed typo in factories.rst (nietonfir) December, 2014 -------------- @@ -1258,41 +940,28 @@ New Documentation ~~~~~~~~~~~~~~~~~ - `00a13d6 `_ #4606 Completely re-reading the security book (weaverryan) -- `aa88f99 `_ #4609 Adding details about the changes to the PdoSessionHandler in 2.6 (weaverryan) - `bd65c3c `_ #4673 [Reference] add validation config reference section (xabbuh) - `55a32cf `_ #4173 use a global Composer installation (xabbuh) - `c5e409b `_ #4526 Deploy Symfony application on Platform.sh. (GuGuss) -- `ddd56ea `_ #4449 Added cache_busting to default asset config (GeertDD) - `c837ea1 `_ #4665 Documented the console environment variables (javiereguiluz) -- `0e45e29 `_ #4655 Document new progressbar methods (javiereguiluz) - `f4a7196 `_ #4627 Rewrite the varnish cookbook article (dbu) - `92a186d `_ #4654 Rewritten from scratch the chapter about installing Symfony (javiereguiluz) - `90ef4ec `_ #4580 Updated installation instructions to use the new Symfony Installer (javiereguiluz) - `f591e6e `_ #4532 GetResponse*Events stop after a response was set (Lumbendil) -- `a09fd7b `_ #4485 Added documentation about the DebugFormatter helper (WouterJ) -- `d327bae `_ #4557 Update pdo_session_storage.rst (spbentz) - `71495e8 `_ #4528 Update web_server_configuration.rst (thePanz) -- `3b9d60d `_ #4517 [Reference] document configurable PropertyAccessor arguments (xabbuh) - `9b330ef `_ #4507 Comply with best practices, Round 2 (WouterJ) - `39a36bc `_ #4405 Finish 3744 (mickaelandrieu, xabbuh) -- `5363542 `_ #4188 Updated documentation regarding the SecurityContext split (iltar) -- `f30f753 `_ #4050 [Translation] added logging capability. (aitboudad) - `db35c42 `_ #4591 Instructions for setting SYMFONY_ENV on Heroku (dzuelke) - `8bba316 `_ #4457 [RFC] Clarification on formatting for bangs (!) (bryanagee) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `79db0b9 `_ #4699 Use new security.authorization_checker service (xelaris) -- `9c819b4 `_ #4713 [Security] Removed deprecated example about SecurityContext (iltar) - `153565e `_ #4707 [Cookbook] Fix XML example for RTE (dunglas) - `cad4d3f `_ #4582 Completed the needed context to successfully test commands with Helpers (peterrehm) - `a137918 `_ #4641 Add missing autoload include in basic console application example (senkal) - `0de8286 `_ #4513 [Contributing] update contribution guide for 2.7/3.0 (xabbuh) -- `8b611e2 `_ #4598 [ExpressionLanguage] add missing argument (xabbuh) - `7ea4b10 `_ #4646 Update the_controller.rst (teggen) -- `a2ea256 `_ #4637 fixed StringExpressionLanguageProvider code example #4636 (danieleorler) -- `63be343 `_ #4630 [OptionsResolver] Fix namespace (xavren) - `baf61a0 `_ #4623 [OptionsResolver] Fix Namespace link (xavren) - `8246693 `_ #4613 Change refering block name from content to body (martin-cerny) - `1750b9b `_ #4599 [Contributing] fix feature freeze dates (xabbuh) @@ -1325,8 +994,6 @@ Minor Documentation Changes - `95fc487 `_ #4608 Removing some installation instructions (weaverryan) - `96455e6 `_ #4539 Normalization of method listings (pedronofuentes) - `bd44e6b `_ #4664 Spelling mistake tens to tons (albabar) -- `3b6341a `_ #4663 Removed double `````firewall_restriction````` entry (vlad-ghita) -- `815e0bf `_ #4551 Normalize the method listings on version 2.5 (pedronofuentes) - `48cc9cd `_ #4647 Update controllers.rst (keefekwan) - `2efed8c `_ #4660 Fix indentation of YAML example (xelaris) - `b55ec30 `_ #4659 Fixed some code indentation (javiereguiluz) @@ -1336,7 +1003,6 @@ Minor Documentation Changes - `9600950 `_ #4617 [Filesystem] filesystem headlines match method names (xabbuh) - `8b006bb `_ #4607 [Best Practices] readd mistakenly removed label (xabbuh) - `7dcce1b `_ #4585 When explaining how to install dependencies for running unit tests, (carlosbuenosvinos) -- `1c9270d `_ #4568 Update Symfony reference to 2.6 version (dangarzon) - `33ca697 `_ #4561 Use the new build env on Travis (joshk) - `107610e `_ #4531 [symfony] [Hackday] Fixed typos (pborreli) - `3b1611d `_ #4519 remove service class parameters (xabbuh) @@ -1351,48 +1017,31 @@ November, 2014 New Documentation ~~~~~~~~~~~~~~~~~ -- `33554fc `_ #4456 New validation API usage in Class Constraint Validator (skwi) - `135aae6 `_ #4433 Completely re-reading the controller chapter (weaverryan) -- `f748378 `_ #4498 Use new factory syntax (WouterJ) -- `59f0374 `_ #4490 Documented ExpressionLanguage extensibility (WouterJ) -- `ed241ab `_ #4487 Documented html5 option (WouterJ) -- `48a5af3 `_ #4486 Renamed empty_value to placeholder (WouterJ) - `422e0f1 `_ #4465 Modifying the best practice to use form_start() instead of
    `_ #4463 [BestPractices] Proposing that we make the service names *just* a little bit longer (weaverryan) -- `9a22865 `_ #4446 [Book][Templating] refer to the VarDumper component for dump() (xabbuh) -- `ed5c61f `_ #4411 Added a reference to the Bootstrap 3 form theme (javiereguiluz) -- `766e01f `_ #4169 [Components][Form] document $deep and $flatten of getErrors() (xabbuh) - `1d88a1b `_ #4443 Added the release dates for the upcoming Symfony 3 versions (javiereguiluz) -- `3329bd2 `_ #4424 [#4243] Tweaks to the new var-dumper component (weaverryan, nicolas-grekas) -- `9caea6f `_ #4336 [Form] Add entity manager instance support for em option (egeloen) - `f2ab245 `_ #4374 [WCM] Revamped the Quick Start tutorial (javiereguiluz) - `2c190ed `_ #4427 Update most important book articles to follow the best practices (WouterJ) - `12a09ab `_ #4377 Added interlinking and fixed install template for reusable bundles (WouterJ) - `8259d71 `_ #4425 Updating component usage to use composer require (weaverryan) - `0e80aba `_ #4369 [reference][configuration][security]Added key_length for pbkdf2 encoder (Guillaume-Rossignol) -- `d1afa4d `_ #4243 [WIP] var-dumper component (nicolas-grekas) - `5165419 `_ #4295 [Security] Hidden front controller for Nginx (phansys) -- `23f790a `_ #4058 Skip console commands from event listeners (tPl0ch) -- `4b98d48 `_ #3386 [Translation] added method to expose collected message (Grygir) -- `242d4f6 `_ #4319 Documentation for debug:event-dispatcher command (matthieuauger) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ - `9d599a0 `_ minor #4544 #4273 - fix doctrine version in How to Provide Model Classes for several Doctrine Implementations cookbook (ternel) - `6aabece `_ #4273 - fix doctrine version in How to Provide Model Classes for several Doctrine Implementations cookbook -- `e96ebd3 `_ #4522 Add missing brackets to PropertyAccessor examples (loonytoons) - `4f66d48 `_ #4506 SetDescription required on Product entities (yearofthegus) - `85bf906 `_ #4444 fix elseif statement (MightyBranch) - `ad14e78 `_ #4494 Updated the Symfony Installer installation instructions (javiereguiluz) -- `7cc4287 `_ #4442 replace doc role for bundle docs with external ref (xabbuh) - `33bf462 `_ #4407 [Components][Console] array options need array default values (xabbuh) - `2ab2e1f `_ #4342 Reworded a misleading Doctrine explanation (javiereguiluz) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `a109c4b `_ #4537 Update link to remove absolute URL (jms85, dangarzon) - `05f5dba `_ #4536 Add Ryan Weaver as 10th core team member (ifdattic) - `7b1ff2a `_ #4554 Changed url to PHP-CS-FIXER repository (jzawadzki) - `9d599a0 `_ #4544 bug #4273 - fix doctrine version in How to Provide Model Classes for several Doctrine Implementations cookbook (ternel) @@ -1400,8 +1049,6 @@ Minor Documentation Changes - `5aaba1e `_ #4529 Best Practices: Update link title to match cookbook article title (dangarzon) - `ab8e7f5 `_ #4530 Book: Update link title to match cookbook article title (dangarzon) - `bf61658 `_ #4523 Add missing semicolons to PropertyAccess examples (loonytoons) -- `8beadce `_ #4496 [Book][Security] link to a bundle's current (not master) docs (xabbuh) -- `43809b1 `_ #4479 remove versionadded directives for old versions (xabbuh) - `5db8386 `_ #4462 [Reference] Fixed lots of things using the review bot (WouterJ) - `dbfaac1 `_ #4459 Fix up the final sentence to be a bit cleaner. (micheal) - `3761e50 `_ #4514 [Contributing][Documentation] typo fix (xabbuh) @@ -1442,36 +1089,23 @@ New Documentation - `d7ef1c7 `_ #4348 Updated information about handling validation of embedded forms to Valid... (peterrehm) - `691b13d `_ #4340 [Cookbook][Web Server] add sidebar for the built-in server in VMs (xabbuh) -- `bd85865 `_ #4299 [Serializer] Handle circular references. symfony/symfony#12098. (dunglas) - `d79c48d `_ #4280 [Cookbook][Cache] Added config example for Varnish 4.0 (thierrymarianne) - `5849f7f `_ #4168 [Components][Form] describe how to access form errors (xabbuh) - `c10e9c1 `_ #4371 Added a code example for emailing on 4xx and 5xx errors without 404's (weaverryan) -- `1117741 `_ #4159 [WCM][OptionsResolver] Adjusted the OptionsResolver documentation to describe the 2.6 API (webmozart, peterrehm) - `0c57939 `_ #4327 First import of the "Official Best Practices" book (javiereguiluz) -- `2cd6646 `_ #4293 Document error page preview (Symfony ~2.6) (mpdude) -- `142c826 `_ #4005 [Cookbook][Web server] description for running PHP's built-in web server in the background (xabbuh) - `8dc90ef `_ #4224 [Components][HttpKernel] outline implications of the kernel.terminate event (xabbuh) - `d3b5ba2 `_ #4085 [Component][Forms] add missing features introduced in 2.3 (xabbuh) - `f433e64 `_ #4099 Composer installation verbosity tip (dannykopping) -- `f583a45 `_ #4204 [Reference][Constraints] validate `````null````` (Expression constraint in 2.6) (xabbuh) - `925a162 `_ #4290 Updating library/bundle install docs to use "require" (weaverryan) -- `86c67e8 `_ #4233 2.5 Validation API changes (nicolassing, lashae, Rootie, weaverryan) -- `0f34bb8 `_ #3956 [Command] Added LockHelper (lyrixx) -- `278de83 `_ #3930 [Console] Add Process Helper documentation (romainneutron) - `44f570b `_ #4294 Improve cookbook entry for error pages in 2.3~ (mpdude) - `3b6c2b9 `_ #4269 [Cookbook][External Parameters] Enhance content (bicpi) -- `25a17fe `_ #4264 [#4003] A few more form_themes config changes (weaverryan) -- `5b65654 `_ #3912 [Security] Added remote_user firewall info and documentation for pre authenticated firewalls (Maxime Douailin, mdouailin) - `62bafad `_ #4246 [Reference] add description for the `````validation_groups````` option (xabbuh) -- `5d505bb `_ #4206 Added note about ProgressBar changes (kbond) - `c2342a7 `_ #4241 [Form] Added information about float choice lists (peterrehm) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `dde6919 `_ #4390 Update custom_constraint.rst (luciantugui) - `68a2c7b `_ #4381 Updated Valid constraint reference (inso) -- `dbb25b9 `_ #4379 [OptionsResolver] Fix wrong namespace in example (rybakit) - `db01e57 `_ #4362 Missing apostrophe in source example. (astery) - `d49d51f `_ #4350 Removed extra parenthesis (sivolobov) - `e6d7d8f `_ #4315 Update choice.rst (odolbeau) @@ -1483,18 +1117,14 @@ Fixed Documentation Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `217bf5f `_ #4353 [Cookbook][Controller] fix route prefix in PHP code example (xabbuh) - `a4f7d51 `_ #4396 Corrected latin abbreviation (GeertDD) - `ebf2927 `_ #4387 Inline condition removed for easier reading (acidjames) - `aa70028 `_ #4375 Removed the redundant usage of layer. (micheal) - `f3dd676 `_ #4394 update Sphinx extension submodule reference (xabbuh) -- `6406a27 `_ #4391 Removed unused use UsernameNotFoundException (boekkooi) - `9e03f2d `_ #4388 Minor spelling fix (GeertDD) - `4dfd607 `_ #4356 Remove incoherence between Doctrine and Propel introduction paragraphs (arnaugm) - `1d71332 `_ #4344 [Templating] Added a sentence that explains what a Template Helper is (iltar) -- `22b9b27 `_ #4372 Tweaks after proofreading the 2.6 OptionsResolver stuff (weaverryan, WouterJ) - `9a76309 `_ #4384 fix typo (kokoon) -- `eb752cc `_ #4363 Fixed sentence (WouterJ) - `3e8aa59 `_ #4376 Cleaned up javascript code (flip111) - `06e7c5f `_ #4364 changed submit button label (OskarStark) - `d1810ca `_ #4357 fix Twig-extensions links (mhor) @@ -1509,15 +1139,12 @@ Minor Documentation Changes - `d162329 `_ #4276 [Components][HttpFoundation] Make a small grammatical adjustment (fabschurt) - `69bfac1 `_ #4322 [Components][DependencyInjection] Correct a typo: replace "then" by "the" (fabschurt) - `8073239 `_ #4318 [Cookbook][Bundles] Correct a typo: remove unnecessary "the" word (fabschurt) -- `228111b `_ #4316 Remove horizontal scrollbar (ifdattic) - `34e22d6 `_ #4317 Remove horizontal scrollbar and change event name to follow conventions (ifdattic) - `090afab `_ #4287 support Varnish in configuration blocks (xabbuh) - `1603463 `_ #4306 Improve readability (ifdattic) -- `e5fed9d `_ #4303 Fix spelling (nurikabe) - `31d7905 `_ #4302 View documentation had a reference to the wrong twig template (milan) - `ef11ef4 `_ #4250 Clarifying Bundle Best Practices is for *reusable* bundles (weaverryan) - `430eabf `_ #4298 Book HTTP Fundamentals routing example fixed with routing.xml file (peterkokot) -- `a535c9f `_ #4285 Update security.rst (placid2000) - `7ab6df9 `_ #4237 Finished #3886 (ahsio, WouterJ) - `990b453 `_ #4245 [Contributing] tweaks to the contribution chapter (xabbuh) @@ -1527,16 +1154,12 @@ September, 2014 New Documentation ~~~~~~~~~~~~~~~~~ -- `e8a1501 `_ #4201 [Components][Process] `````mustRun()````` documentation (xabbuh) - `eac0e51 `_ #4195 Added a note about the total deprecation of YUI (javiereguiluz) - `e44c791 `_ #4047 Documented info method (WouterJ) -- `2962e14 `_ #4003 [Twig][Form] Moved twig.form.resources to a higher level (stefanosala) - `d5d46ec `_ #4017 Clarify that route defaults don't need a placeholder (iamdto) - `1d56da4 `_ #4239 Remove redundant references to trusting HttpCache (thewilkybarkid) - `c306b68 `_ #4249 provide node path on configuration (desarrolla2) -- `9f0f14e `_ #4210 Move debug commands to debug namespace (matthieuauger) - `9b4b36f `_ #4236 Javiereguiluz bundle install instructions (WouterJ) -- `ea068c2 `_ #4202 [Reference][Constraints] caution on `````null````` values in Expression constraint (xabbuh) - `a578de9 `_ #4223 Revamped the documentation about "Contributing Docs" (javiereguiluz) - `de60dbe `_ #4182 Added note about exporting SYMFONY_ENV (jpb0104) - `a8dc2bf `_ #4166 Translation custom loaders (raulfraile) @@ -1544,19 +1167,16 @@ New Documentation Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `c289ac8 `_ #4279 Double-quotes instead of single quotes (UnexpectedValueException in Windows 8) (galdiolo) - `5500e0b `_ #4267 Fix error in bundle installation standard example (WouterJ) - `082755d `_ #4240 [Components][EventDispatcher] fix ContainerAwareEventDispatcher definition (xabbuh) - `2319d6a `_ #4213 Handle "constraints" option in form unit testing (sarcher) - `c567707 `_ #4222 [Components][DependencyInjection] do not reference services in parameters (xabbuh) -- `02d1091 `_ #4209 Fix method for adding placholders in progressBar (danez) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - `df16779 `_ #4226 add note about parameters in imports (xabbuh) - `c332063 `_ #4278 Missing word in DependencyInjection => Types of Injection (fabschurt) -- `287c7bf `_ #4275 added Nicolas to the list of mergers for the new var dumper component (fabpot) - `3a4e226 `_ #4263 Fixed typo (zebba) - `187c255 `_ #4259 Added feature freeze dates for Symfony versions (javiereguiluz) - `efc1436 `_ #4247 [Reference] link translation DIC tags to components section (xabbuh) @@ -1569,7 +1189,6 @@ Minor Documentation Changes - `2cf9e47 `_ #4171 Fixed version for composer install (zomberg) - `5c62b36 `_ #4216 Update Collection.rst (azarzag) - `8591b87 `_ #4215 Fixed code highlighting (WouterJ) -- `8f01195 `_ #4212 Missing backtick, thanks to @Baptouuuu (WouterJ) - `f276e34 `_ #4205 replace "Symfony2" with "Symfony" (xabbuh) - `6db13ac `_ #4208 Added a note about the lacking features of Yaml Component (javiereguiluz) - `f8c6201 `_ #4200 Moved 'contributing' images to their own directory (javiereguiluz) @@ -1585,46 +1204,35 @@ New Documentation - `bccb080 `_ #4140 [Cookbook][Logging] document multiple recipients in XML configs (xabbuh) - `7a6e3d1 `_ #4150 Added the schema_filter option to the reference (peterrehm) - `be90d8a `_ #4142 [Cookbook][Configuration] tweaks for the web server configuration chapter (xabbuh) -- `5379f54 `_ #4086 [Reference][Constraints] Added hint about attaching the expression constraint to a form field (peterrehm) - `041105c `_ #3883 Removed redundant POST request exclusion info (ryancastle) - `4f9fef6 `_ #4000 [Cookbook] add cookbook article for the server:run command (xabbuh) - `4ea4dfe `_ #3915 [Cookbook][Configuration] documentation of Apache + PHP-FPM (xabbuh) -- `79cb4f1 `_ #4069 document the namespace alias (dbu) -- `08bed5f `_ #4128 Finished #3759 (WouterJ) - `4d5adaa `_ #4125 Added link to JSFiddle example (WouterJ) - `75bda4b `_ #4124 Rebased #3965 (WouterJ) -- `e2f13a4 `_ #4039 [DomCrawler] Added node name getter (fejese) -- `3f92d5f `_ #3966 [Cookbook][Controller] Add note about invokable controller services (kbond) - `fdb8a32 `_ #3950 [Components][EventDispatcher] describe the usage of the RegisterListenersPass (xabbuh) - `7e09383 `_ #3940 Updated docs for Monolog "swift" handler in cookbook. (phansys) -- `9d7c999 `_ #3895 [Validator] Support "maxSize" given in KiB (jeremy-derusse) - `8adfe98 `_ #3894 Rewrote Extension & Configuration docs (WouterJ) - `cafea43 `_ #3888 Updated the example used to explain page creation (javiereguiluz) - `df0cf68 `_ #3885 [RFR] Added "How to Organize Configuration Files" cookbook (javiereguiluz) - `41116da `_ #4081 [Components][ClassLoader] documentation for the ClassMapGenerator class (xabbuh) -- `2b9cb7c `_ #4076 Fixed description of session storage of the ApiKeyAuthenticator (peterrehm) - `35a0f66 `_ #4102 Adding a new entry about reverse proxies in the framework (weaverryan) - `95c2066 `_ #4096 labels in submit buttons + new screenshot (ricardclau) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `5fac303 `_ #4165 Update voters.rst (gerryvdm) - `4882b99 `_ #4164 Fixed minor typos. (ahsio) - `eaaa35a `_ #4145 Fix documentation for group_sequence_provider (giosh94mhz) -- `155c3e8 `_ #4153 [Reference] fix namespace in Expression constraint (xabbuh) - `2c93aa5 `_ #4147 [Cookbook][Logging] add missing Monolog handler type in XML config (xabbuh) - `53b2c2b `_ #4139 cleaned up the code example (gondo) - `b5c9f2a `_ #4138 fixed wrongly linked dependency (gondo) - `b486b22 `_ #4131 Replaced old way of specifying http method by the new one (Baptouuuu) - `93481d7 `_ #4120 Fix use mistakes (mbutkereit) - `c0a0120 `_ #4119 Fix class name in ConsoleTerminateListener example (alOneh) -- `4629d8b `_ #4116 Fixed the code snippets for the expression language functions (stof) - `d699255 `_ #4083 [Reference] field dependent empty_data option description (xabbuh) - `3ffc20f `_ #4103 [Cookbook][Forms] fix PHP template file name (xabbuh) - `234fa36 `_ #4095 Fix php template (piotrantosik) - `01fb9f2 `_ #4093 See #4091 (dannykopping) -- `8f3a261 `_ #4092 See #4091 (dannykopping) - `7d39b03 `_ #4079 Fixed typo in filesystem component (kohkimakimoto) - `f0bde03 `_ #4075 Fixed typo in the yml validation (timothymctim) @@ -1633,13 +1241,11 @@ Minor Documentation Changes - `e9d317a `_ #4160 [Reference] consistent & complete config examples (xabbuh) - `3e68ee7 `_ #4152 Adding 'attr' option to the Textarea options list (ronanguilloux) -- `a7f3297 `_ #4136 [Reference] fix from suffix to prefix (xabbuh) - `c4eb628 `_ #4130 A set of small typos (Baptouuuu) - `236d8e0 `_ #4137 fixed directive syntax (WouterJ) - `6e90520 `_ #4135 [#3940] Adding php example for an array of emails (weaverryan) - `b37ee61 `_ #4132 Use proper way to reference a doc page for legacy sessions (Baptouuuu) - `189a123 `_ #4129 [Components] consistent & complete config examples (xabbuh) -- `5ab5246 `_ #4127 Second part of #3848 (WouterJ) - `46f3108 `_ #4126 Rebased #3848 (WouterJ) - `84e6e7f `_ #4114 [Book] consistent and complete config examples (xabbuh) - `03fcab1 `_ #4112 [Contributing][Documentation] add order of translation formats (xabbuh) @@ -1654,7 +1260,6 @@ Minor Documentation Changes - `7806aa7 `_ #4117 Added a note about the automatic handling of the memory spool in the CLI (stof) - `5959b6c `_ #4101 [Contributing] extended Symfony 2.4 maintenance (xabbuh) - `e2056ad `_ #4072 [Contributing][Code] add note on Symfony SE forks for bug reports (xabbuh) -- `b8687dd `_ #4091 Put version into quotes, otherwise it fails in ZSH (dannykopping) - `665c091 `_ #4087 Typo (tvlooy) - `f95bbf3 `_ #4023 [Cookbook][Security] usage of a non-default entity manager in an entity user provider (xabbuh) - `27b1003 `_ #4074 Fixed (again) a typo: Toolbet --> Toolbelt (javiereguiluz) @@ -1671,12 +1276,8 @@ New Documentation - `1b4c1c8 `_ #4045 Added a new "Deploying to Heroku Cloud" cookbook article (javiereguiluz) - `f943eee `_ #4009 Remove "Controllers extends ContainerAware" best practice (tgalopin) - `eae9ad0 `_ #3875 Added a note about customizing a form with more than one template (javiereguiluz) -- `2ae4f34 `_ #3746 [Validator] Disallow empty file in FileValidator (megazoll) -- `1938c2f `_ #3724 Updated ISBN validator docs (sprain) -- `7c71b18 `_ #2952 Enabling profiler in test (danieledangeli) - `d6787b7 `_ #3989 adde stof as a merger (fabpot) - `4a9e49e `_ #3946 DQL custom functions on doctrine reference page (healdropper) -- `2b2d9d3 `_ #3972 Added PSR-4 to Class Loaders list (dosten) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ @@ -1684,18 +1285,12 @@ Fixed Documentation - `1b695b5 `_ #4063 fix parent form types (xabbuh) - `7901005 `_ #4048 $this->request replaced by $request (danielsan) - `f6123f1 `_ #4031 Update form_events.rst (redstar504) -- `99932cf `_ #4010 [Console] Fixed documentation for ProgressBar (VasekPurchart) -- `06f8c31 `_ #4012 Fix xml route configuration for routing condition (xavierbriand) -- `a2a628f `_ #4025 added CVE 2014-4931 (fabpot) -- `a1435e5 `_ #3998 [Console] Fixed QuestionHelper examples (florianv) -- `b32f9f2 `_ #3771 Fix function example in expression language component (raulfraile) - `eb813a5 `_ #3979 removed invalid processors option (ricoli) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - `a4bdb97 `_ #4070 Added a note about permissions in the Quick Tour (javiereguiluz) -- `a7fe00f `_ #4068 Remove diff info from cookbook/security/voters.rst (pmartelletti) - `b3f15b2 `_ #4059 eraseCredentials method typo (danielsan) - `44091b1 `_ #4053 Update doctrine.rst (sr972) - `b06ad60 `_ #4052 [Security] [Custom Provider] Use properties on WebserviceUser (entering) @@ -1708,11 +1303,7 @@ Minor Documentation Changes - `f5c2602 `_ #4036 Update page_creation.rst (redstar504) - `c2eda93 `_ #4034 Update internals.rst (redstar504) - `a5ad0df `_ #4035 Update version in Rework your Patch section (yguedidi) -- `eed8d64 `_ #4026 Updating Symfony version from 2.4 to 2.5 (danielsan) -- `12752c1 `_ #4013 Removed wrong reference to cookbook (gquemener) -- `ec832dc `_ #3994 [Console] Fix Console component $app to $this and use of getHelper() method (eko) - `d8b037a `_ #4019 Update twig_reference.rst (redstar504) -- `7ea87e6 `_ #4016 Fixed the format of one letter-based list (javiereguiluz) - `579a873 `_ #4015 Fixed bad indenting (the list was treated as a blockquote) (javiereguiluz) - `4669620 `_ #4004 use GitHub instead of Github (xabbuh) - `a3fe74f `_ #3993 [Console] Fix Console component getHelperSet()->get() to getHelper() (eko) @@ -1739,15 +1330,12 @@ New Documentation - `23b51c8 `_ #3901 Bootstraped the standards for "Files and Directories" (javiereguiluz) - `8931c36 `_ #3889 Fixed the section about getting services from a command (javiereguiluz) - `9fddab6 `_ #3877 Added a note about configuring several paths under the same namespace (javiereguiluz) -- `eadf281 `_ #3874 Updated the installation instructions for Symfony 2.5+ (javiereguiluz) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ - `aeffd12 `_ #3961 Fixing php coding (mvhirsch) -- `84332ff `_ #3945 Fixed missing component name in namespaces (WouterJ) - `d8329dc `_ #3943 Fixing simple quotes in double quotes (ptitlazy) -- `04f4318 `_ #3934 Move __construct after the repository assignment (cmodijk) - `0626f2b `_ #3897 Collection constraint (hhamon) - `3387cb2 `_ #3871 Fix missing Front Controller (parthasarathigk) - `8257be9 `_ #3891 Fixed wrong method call. (cmfcmf) @@ -1761,18 +1349,11 @@ Minor Documentation Changes - `fba083e `_ #3957 [Cookbook][Bundles] fix typos in the prepend extension chapter (xabbuh) - `c444b5d `_ #3948 update the Sphinx extensions to raise warnings when backslashes are not ... (xabbuh) - `8fef7b7 `_ #3938 [Contributing][Documentation] don't render the list inside a blockquote (xabbuh) -- `b7a03f8 `_ #3937 properly escape backslashes in class and method directives (xabbuh) -- `882471f `_ #3935 Typo (greg0ire) - `222a014 `_ #3933 render directory inside a code block (xabbuh) -- `0c2a9b3 `_ #3931 [Component][EventDispatcher] 2.5 specific documentation for the TraceableEventDispatcher (xabbuh) -- `b31ea51 `_ #3929 Update custom_authentication_provider.rst (verschoof) - `7937864 `_ #3927 [Cookbook][Security] Explicit 'your_user_provider' configuration parameter (zefrog) - `26d00d0 `_ #3925 Fixed the indentation of two code blocks (javiereguiluz) - `351b2cf `_ #3922 update fabpot Sphinx extensions version (xabbuh) -- `3ddbe1b `_ #3923 Fixed the headers of one table (javiereguiluz) - `35cbffc `_ #3920 [Components][Form] remove blank line to render the versionadded directive properly (xabbuh) -- `df9f31a `_ #3882 change version numbers in installation notes to be in line with the docu... (xabbuh) -- `ed496ae `_ #3887 [Components][Form] add versionadded for the data collector form extension (xabbuh) - `36337e7 `_ #3906 Blockquote introductions (xabbuh) - `5e0e119 `_ #3899 [RFR] Misc. fixes mostly related to formatting issues (javiereguiluz) - `349cbeb `_ #3900 Fixed the formatting of the table headers (javiereguiluz) @@ -1786,14 +1367,10 @@ May, 2014 New Documentation ~~~~~~~~~~~~~~~~~ -- `4fd1b49 `_ #3753 [DependencyInjection] Add documentation about service decoration (romainneutron) -- `f913dd7 `_ #3603 [Serializer] Support for is.* getters in GetSetMethodNormalizer (tiraeth) -- `e8511cb `_ #3776 Updated event_listener.rst (bfgasparin) - `af8c20f `_ #3818 [Form customization] added block_name example. (aitboudad) - `c788325 `_ #3841 [Cookbook][Logging] register processor per handler and per channel (xabbuh) - `979533a `_ #3839 document how to test actions (greg0ire) - `d8aaac3 `_ #3835 Updated framework.ide configuration (WouterJ) -- `a9648e8 `_ #3742 [2.5][Templating] Add documentation about generating versioned URLs (romainneutron) - `f665e14 `_ #3704 [Form] Added documentation for Form Events (csarrazi) - `14b9f14 `_ #3777 added docs for the core team (fabpot) @@ -1807,7 +1384,6 @@ Fixed Documentation - `4ed9a08 `_ #3830 Generate an APC prefix based on __FILE__ (trsteel88) - `9a65412 `_ #3840 Update dialoghelper.rst (jdecoster) - `1853fea `_ #3716 Fix issue #3712 (umpirsky) -- `baa9759 `_ #3791 Property access tweaks (weaverryan) - `80d70a4 `_ #3779 [Book][Security] constants are defined in the SecurityContextInterface (xabbuh) Minor Documentation Changes @@ -1815,13 +1391,11 @@ Minor Documentation Changes - `302fa82 `_ #3872 Update hostname_pattern.rst (sofany) - `50672f7 `_ #3867 fixed missing info about FosUserBundle. (aitboudad) -- `3e3004f `_ #3865 Fixed link. (aitboudad) - `b32ec15 `_ #3856 Update voters_data_permission.rst (MarcomTeam) - `bffe163 `_ #3859 Add filter cssrewrite (DOEO) - `f617ff8 `_ #3764 Update testing.rst (NAYZO) - `3792fee `_ #3858 Clarified Password Encoders example (WouterJ) - `663d68c `_ #3857 Added little bit information about the route name (WouterJ) -- `797cbd5 `_ #3794 Adds link to new QuestionHelper (weaverryan) - `4211bff `_ #3852 Fixed link and typo in type_guesser.rst (rpg600) - `78ae7ec `_ #3845 added link to /cookbook/security/force_https. (aitboudad) - `6c69362 `_ #3846 [Routing][Loader] added JMSI18nRoutingBundle (aitboudad) @@ -1829,14 +1403,10 @@ Minor Documentation Changes - `b0710bc `_ #3842 Update dialoghelper.rst (bijsterdee) - `9f1a354 `_ #3804 [Components][DependencyInjection] add note about a use case that requires to compile the container (xabbuh) - `d92c522 `_ #3769 Updated references to new Session() (scottwarren) -- `00f60a8 `_ #3837 More asset version details (weaverryan) -- `681ddc8 `_ #3843 [Changelog] fix literal positions (xabbuh) -- `1aa79d5 `_ #3834 fix the wording in versionadded directives (for the master branch) (xabbuh) - `7288a33 `_ #3789 [Reference][Forms] Improvements to the form type (xabbuh) - `72fae25 `_ #3790 [Reference][Forms] move versionadded directives for form options directly below the option's headline (xabbuh) - `b4d4ac3 `_ #3838 fix filename typo in cookbook/form/unit_testing.rst (hice3000) - `0b06287 `_ #3836 remove unnecessary rewrite from nginx conf (Burgov) -- `89d0dae `_ #3833 fix the wording in versionadded directives (for the 2.4 branch) (xabbuh) - `e58e39f `_ #3832 fix the wording in versionadded directives (for the 2.3 branch) (xabbuh) - `09d6ca1 `_ #3829 [Components] consistent headlines (xabbuh) - `54e0882 `_ #3828 [Contributing] consistent headlines (xabbuh) @@ -1852,7 +1422,6 @@ Minor Documentation Changes - `241d923 `_ #3813 [Reference][Forms]fix time field count. (yositani2002) - `bc96f55 `_ #3812 [Cookbook][Configuration] Fixed broken link. (ahsio) - `5867327 `_ #3809 Fixed typo (WouterJ) -- `678224e `_ #3808 Fixed broken link in "Handling Authentication Failure" (stacyhorton) April, 2014 ----------- @@ -1861,15 +1430,9 @@ New Documentation ~~~~~~~~~~~~~~~~~ - `322972e `_ #3803 [Book][Validation] configuration examples for the GroupSequenceProvider (xabbuh) -- `9e129bc `_ #3752 [Console] Add documentation for QuestionHelper (romainneutron) -- `64a924d `_ #3756 [WCM][Console] Add Process Helper documentation (romainneutron) - `d4ca16a `_ #3743 Improve examples in parent services (WouterJ) -- `be4b9d3 `_ #3729 Added documentation for the new ``PropertyAccessor::isReadable()`` and ``isWritable()`` methods (webmozart) -- `70a3893 `_ #3774 [Book][Internals] add description for the kernel.finish_request event (xabbuh) -- `1934720 `_ #3461 [Form] Deprecated max_length and pattern options (stefanosala) - `d611e77 `_ #3701 [Serializer] add documentation for serializer callbacks (cordoval) - `80c645c `_ #3719 Fixed event listeners priority (tony-co) -- `c062d81 `_ #3469 [Validator] - EmailConstraint reference (egulias) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ @@ -1877,7 +1440,6 @@ Fixed Documentation - `f801e2e `_ #3805 Add missing autocomplete argument in askAndValidate method (ifdattic) - `a81d367 `_ #3786 replaceArguments should be setArguments (RobinvdVleuten) - `33b64e1 `_ #3788 Fix link for StopwatchEvent class (rpg600) -- `2ebabfb `_ #3792 Update commands_as_services.rst (mimol91) - `529d4ce `_ #3761 buildViewBottomUp has been renamed to finishView (Nyholm) - `d743139 `_ #3768 the Locale component does not have elements tagged with @api (xabbuh) - `2b8e44d `_ #3747 Fix Image constraint class and validator link (weaverryan) @@ -1887,7 +1449,6 @@ Fixed Documentation Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `136f98c `_ #3784 [Expression Langage] be consistent in "print/print out" uses (mickaelandrieu) - `1094a13 `_ #3807 Added some exceptions to the method order in CS (stof) - `55442b5 `_ #3800 Fixed another blockquote rendering issue (WouterJ) - `969fd71 `_ #3785 ensure that destination directories don't exist before creating them (xabbuh) @@ -1901,10 +1462,7 @@ Minor Documentation Changes - `703c2a6 `_ #3772 [Cookbook][Sessions] some language improvements (xabbuh) - `3d30b56 `_ #3773 modify Symfony CMF configuration values in the build process so that the... (xabbuh) - `cfd6d7c `_ #3758 [Book][Routing] Fixed typo on PHP version of a route definition (saro0h) -- `cedfdce `_ #3757 Fixed a typo in the request formats configuration page (gquemener) - `6bd134c `_ #3754 ignore more files and directories which are created when building the documentation (xabbuh) -- `610462e `_ #3755 [Cookbook][Security] Firewall resitrction tweaks, fix markup, add to toc (xabbuh) -- `0a21718 `_ #3695 Firewall backport (weaverryan) - `54d6a9e `_ #3736 [book] Misc. routing fixes (javiereguiluz) - `f149dcf `_ #3739 [book] [forms] misc. fixes and tweaks (javiereguiluz) - `ce582ec `_ #3735 [book] [controller] fixed the code of a session sample code (javiereguiluz) @@ -1921,33 +1479,18 @@ New Documentation - `3b640aa `_ #3644 made some small addition about our BC promise and semantic versioning (fabpot) - `2d1ecd9 `_ #3525 Update file_uploads.rst (juanmf) - `b1e8f56 `_ #3368 The host parameter has to be in defaults, not requirements (MarieMinasyan) -- `b34fb64 `_ #3619 [Validator] Uuid constraint reference (colinodell) -- `d7027c0 `_ #3418 [Validation] Add "hasser" support (bicpi) -- `4fd5fc1 `_ #3539 [Stopwatch] Describe retrieval of StopwatchEvent (jochenvdv) -- `1908a15 `_ #3696 [Console] Added standalone PSR-3 compliant logger (dunglas) -- `c75b1a7 `_ #3621 [Console] Command as service (gnugat) - `00a462a `_ minor #3658 Fix PSR coding standards error (ifdattic) - `acf255d `_ #3328 [WIP] Travis integration (WouterJ) -- `450146e `_ #3681 Enhanced Firewall Restrictions docs (danez) - `3e7028d `_ #3659 [Internals] Complete notification description for kernel.terminate (bicpi) - `db3cde7 `_ #3124 Add note about the property attribute (Property Accessor) (raziel057) - `5965ec8 `_ #3420 [Cookbook][Configuration] add configuration cookbook handlig parameters in Configurator class (cordoval) -- `dcf8e6e `_ #3402 Added documentation about new requests formats configuration (gquemener) - `a1050eb `_ #3411 [Cookbook][Dynamic Form Modification] Add AJAX sample (bicpi) -- `842fd30 `_ #3683 [TwigBundle] Add documentation about generating absolute URL with the asset function (romainneutron) -- `fc1576a `_ #3664 [Process] Add doc for ``Process::disableOutput`` and ``Process::enableOutput`` (romainneutron) -- `3731e2e `_ #3686 Documentation of the new PSR-4 class loader. (derrabus) -- `5b915c2 `_ #3629 Added documentation for translation:debug (florianv) - `6951460 `_ #3601 Added documentation for missing ctype extension (slavafomin) -- `df63740 `_ #3627 added docs for the new Table console helper (fabpot) -- `96bd81b `_ #3626 added documentation for the new Symfony 2.5 progress bar (fabpot) -- `b02c16a `_ #3565 added information on AuthenticationFailureHandlerInterface (samsamm777) - `2657ee7 `_ #3597 Document how to create a custom type guesser (WouterJ) - `5ad1599 `_ #3577 Development of custom error pages is impractical if you need to set kernel.debug=false (mpdude) - `3f4b319 `_ #3610 [HttpFoundation] Add doc for ``Request::getContent()`` method (bicpi) - `56bc266 `_ #3589 Finishing the Templating component docs (WouterJ) - `d881181 `_ #3588 Documented all form variables (WouterJ) -- `5cda1c7 `_ #3311 Use KernelTestCase instead of WebTestCase for testing code only requiring the Container (johnkary) - `e96e12d `_ #3234 [Cookbook] New cookbok: How to use the Cloud to send Emails (bicpi) - `d5d64ce `_ #3436 [Reference][Form Types] Add missing docs for "action" and "method" option (bicpi) - `3df34af `_ #3490 Tweaking Doctrine book chapter (WouterJ) @@ -1956,7 +1499,6 @@ New Documentation Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `cad38ae `_ #3721 tweaks to the Console logger (xabbuh) - `06c56c1 `_ #3709 [Components][Security] Fix #3708 (bicpi) - `aadc61d `_ #3707 make method supportsClass() in custom voter compatible with the interface's documentation (xabbuh) - `65150f9 `_ #3637 Update render_without_controller.rst (94noni) @@ -1971,7 +1513,6 @@ Fixed Documentation - `0c41762 `_ #3600 [Security][Authentication] Fix instructions for creating password encoders (bicpi) - `0ab1f24 `_ #3593 Clarified Default and ClassName groups (WouterJ) - `178984b `_ #3648 [Routing] Remove outdated tip about sticky locale (bicpi) -- `fc28453 `_ #3039 use DebugClassLoader class from Decomponent instead of the one from ... (xabbuh) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1979,18 +1520,13 @@ Minor Documentation Changes - `abca098 `_ #3726 Minor tweaks after merging #3644 by @stof and @xabbuh (weaverryan) - `d16be31 `_ #3725 Minor tweaks related to #3368 (weaverryan) - `aa9bb25 `_ #3636 Update security.rst (nomack84) -- `78425c6 `_ #3722 add "Commands as Services" chapter to the cookbook's map (xabbuh) - `9f26da8 `_ #3720 [#3539] A backport of a sentence - the parts that apply to 2.3 (weaverryan) -- `4b611d6 `_ #3717 [master] Fixed versionadded blocks (WouterJ) - `5a3ba1b `_ #3715 change variable name to a better fitting one (xabbuh) -- `499eb6c `_ #3714 [2.4] Versionadded consistency (WouterJ) - `e7580c0 `_ #3713 Updated versionadded directives to use "introduced" (WouterJ) - `e15afe0 `_ #3711 Simplified the Travis configuration (stof) -- `db1cda5 `_ #3700 [Cookbook][Security] Firewall restrictions tweaks (xabbuh) - `5035837 `_ #3706 Add support for nginx (guiditoito) - `00a462a `_ #3658 Fix PSR coding standards error (ifdattic) - `868de1e `_ #3698 Dynamic form modification cookbook: Fix inclusion of code (michaelperrin) -- `15a9d25 `_ #3697 [Console] Change Command namespaces (dunglas) - `41b2eb8 `_ #3693 Tweak to Absolute URL generation (weaverryan) - `bd473db `_ #3563 Add another tip to setup permissions (tony-co) - `67129b1 `_ #3611 [Reference][Forms] add an introductory table containing all options of the basic form type (xabbuh) @@ -2004,19 +1540,14 @@ Minor Documentation Changes - `12a6676 `_ #3640 [minor] fixed one typo and one formatting issue (javiereguiluz) - `9967b0c `_ #3638 [#3116] Fixing wrong table name - singular is used elsewhere (weaverryan) - `4fbf1cd `_ #3635 [QuickTour] close opened literals (xabbuh) -- `27b3410 `_ #3692 [Book][Translations] fixing a code block (xabbuh) - `2192c32 `_ #3650 Fixing some build errors (xabbuh) - `fa3f531 `_ #3677 [Reference][Forms] Remove variables section from tables (xabbuh) -- `cd6d1de `_ #3676 remove unnecessary code block directive (xabbuh) -- `07822b8 `_ #3675 add missing code block directive (xabbuh) -- `739f43f `_ #3669 Fixed syntax highlighting (rvanlaarhoven) - `1f384bc `_ #3631 Added documentation for message option of the ``True`` constraint (naitsirch) - `f6a41b9 `_ #3630 Minor tweaks to form action/method (weaverryan) - `ae755e0 `_ #3628 Added anchor for permissions (WouterJ) - `6380113 `_ #3667 Update index.rst (NAYZO) - `97ef2f7 `_ #3566 Changes ACL permission setting hints (MicheleOnGit) - `9f7d742 `_ #3654 [Cookbook][Security] Fix VoterInterface signature (bicpi) -- `0a65b6f `_ #3608 [Reference][Forms] add versionadded directive for multiple option of file type (xabbuh) - `e34204e `_ #3605 Fixed a plural issue (benjaminpaap) - `e7d5a45 `_ #3599 [CHANGELOG] fix reference to contributing docs (xabbuh) - `3582bf1 `_ #3598 add changelog to hidden toctree (xabbuh) @@ -2038,37 +1569,25 @@ New Documentation - `89c6f1d `_ #3439 [Review] Added detailed Backwards Compatibility Promise text (webmozart) - `0029408 `_ #3558 Created Documentation CHANGELOG (WouterJ) - `f6dd678 `_ #3548 Update forms.rst (atmosf3ar) -- `9676f2c `_ #3523 [Components][EventDispatcher] describe that the event name and the event dispatcher are passed to even... (xabbuh) -- `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) - `527c8b6 `_ #3496 Added a section about using named assets (vmattila) -- `8ccfe85 `_ #3491 Added doc for named encoders (tamirvs) -- `46377b2 `_ #3486 Documenting createAccessDeniedException() method (klaussilveira) Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `5c4336a `_ #3570 Callback: [Validator, validate] expects validate to be static (nixilla) - `5c367b4 `_ #3517 Fixed OptionsResolver component docs (WouterJ) - `adcbb5d `_ #3615 Fixes to cookbook/doctrine/registration_form.rst (Crushnaut) - `a21fb26 `_ #3559 Remove reference to copying parameters.yml from Git cookbook (pwaring) - `de71a51 `_ #3551 [Cookbook][Dynamic Form Modification] Fix sample code (rybakit) - `143db2f `_ #3550 Update introduction.rst (taavit) - `384538b `_ #3549 Fixed createPropertyAccessorBuilder usage (antonbabenko) -- `642e776 `_ #3544 Fix build errors (xabbuh) - `d275302 `_ #3541 Update generic_event.rst (Lumbendil) - `819949c `_ #3537 Add missing variable assignment (colinodell) - `d7e8262 `_ #3535 fix form type name. (yositani2002) - `821af3b `_ #3493 Type fix in remove.rst (weaverryan) - `003230f `_ #3530 Update form_customization.rst (dczech) -- `a43f15a `_ #3519 [Book][Service Container] Fix syntax highlighting (iamdto) -- `86e02c6 `_ #3514 Fixed some small typos in code example (RobinvdVleuten) - `696313c `_ #3513 [Component-DI] Fixed typo (saro0h) - `27dcebd `_ #3509 Fix typo: side.bar.twig => sidebar.twig (ifdattic) -- `0dc8c26 `_ #3507 Fix a typo (missing `````) in ``:doc:`` link (ifdattic) -- `272197b `_ #3504 fix include directive so that the contents are really included (xabbuh) - `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) -- `6d34aa6 `_ #3478 Update custom_password_authenticator.rst (piotras-s) -- `a171700 `_ #3477 Api key user provider should use "implements" instead of "extends" (skowi) - `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) - `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) @@ -2079,17 +1598,13 @@ Minor Documentation Changes - `38def3b `_ #3567 Update checkbox_compound.rst.inc (joshuaadickerson) - `15d8ab8 `_ #3553 Minimize horizontal scrolling in code blocks to improve readability (ifdattic) - `5120863 `_ #3547 Update acl.rst (iqfoundry) -- `b7ac326 `_ #3557 Minimize horizontal scrolling in code block to improve readability (ifdattic) - `d974c77 `_ #3556 Fix PSR error (ifdattic) - `f4bb017 `_ #3555 Wrap variables in {} for safer interpolation (ifdattic) - `5f02bca `_ #3552 Fix typos (ifdattic) - `6e32c47 `_ #3546 Fix README: contributions should be based off 2.3 or higher (colinodell) - `ffa8f76 `_ #3545 Example of getting entity managers directly from the container (colinodell) - `6a2a55b `_ #3579 Fix build errors (xabbuh) -- `dce2e23 `_ #3532 Added tip for Entity Listeners (slavafomin) - `73adf8b `_ #3528 Clarify service parameters usages (WouterJ) -- `7e75b64 `_ #3533 Moving the new named algorithms into their own cookbook entry (weaverryan) -- `f634600 `_ #3531 Remove horizontal scrolling in code block (ifdattic) - `9ba4fa7 `_ #3527 Changes to components domcrawler (ifdattic) - `8973c81 `_ #3526 Changes for Console component (ifdattic) - `6848bed `_ #3538 Rebasing #3518 (weaverryan) @@ -2110,41 +1625,40 @@ January, 2014 New Documentation ~~~~~~~~~~~~~~~~~ -- `d52f3f8 `_ #3454 [Security] Add host option (ghostika) -- `11e079b `_ #3446 [WCM] Documented deprecation of the apache router. (jakzal) -- `0a0bf4c `_ #3437 Add info about callback in options resolver (marekkalnik) -- `6db5f23 `_ #3426 New Feature: Change the Default Command in the Console component (danielcsgomes) -- `6b3c424 `_ #3428 Translation - Added info about JsonFileLoader added in 2.4 (singles) +No changes Fixed Documentation ~~~~~~~~~~~~~~~~~~~ -- `fb22fa0 `_ #3456 remove duplicate label (xabbuh) -- `a87fe18 `_ #3470 Fixed typo (danielcsgomes) +- `e385d28 `_ #3503 file extension correction xfliff to xliff (nixilla) +- `7fe0de3 `_ #3475 Fixed doc for framework.session.cookie_lifetime refrence. (tyomo4ka) +- `8155e4c `_ #3473 Update proxy_examples.rst (AZielinski) - `c205bc6 `_ #3468 enclose YAML string with double quotes to fix syntax highlighting (xabbuh) - `89963cc `_ #3463 Fix typos in cookbook/testing/database (ifdattic) - `e0a52ec `_ #3460 remove confusing outdated note on interactive rebasing (xabbuh) - `6831b13 `_ #3455 [Contributing][Code] fix indentation so that the text is rendered properly (xabbuh) - `ea5816f `_ #3433 [WIP][Reference][Form Types] Update "radio" form type (bicpi) - `42c80d1 `_ #3448 Overridden tweak (weaverryan) -- `bede4c3 `_ #3447 Fix error in namespace when use TokenInterface (joanteixi) - `d9d7c58 `_ #3444 Fix issue #3442 (ifdattic) -- `a6ad607 `_ #3441 [Expression]Change title 'Accessing Public Methods' (Pyrech) - `9e2e64b `_ #3427 Removed code references to Symfony Standard Distribution (danielcsgomes) -- `3c2c5fc `_ #3435 Update custom_password_authenticator.rst (boardyuk) - `26b8146 `_ #3415 [#3334] the data_class option was not introduced in 2.4 (xabbuh) - `0b2a491 `_ #3414 add missing code-block directive (xabbuh) - `4988118 `_ #3432 [Reference][Form Types] Add "max_length" option in form type (nykopol) - `26a7b1b `_ #3423 [Session Configuration] add clarifying notes on session save handler proxies (cordoval) -- `f2f5e9a `_ #3421 [Contributing] Cleaning the "contributing patch" page a bit (lemoinem) Minor Documentation Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- `1131247 `_ #3508 Add 'in XML' for additional clarity (ifdattic) +- `a650b93 `_ #3506 Nykopol overriden options (weaverryan) +- `ab10035 `_ #3505 replace Akamaï with Akamai (xabbuh) +- `7f56c20 `_ #3501 [Security] Fix markup (tyx) +- `80a90ba `_ #3500 Minimize horizontal scrolling in code blocks (improve readability) (ifdattic) +- `e5bc4ea `_ #3498 Remove second empty data (xabbuh) +- `d084d87 `_ #3485 [Cookbook][Assetic] Fix "javascripts" tag name typo (bicpi) +- `3250aba `_ #3481 Fix code block (minimise horizontal scrolling), typo in yaml (ifdattic) - `f285d93 `_ #3451 some language tweaks (AE, third-person perspective) (xabbuh) -- `b9bbe5d `_ #3499 Fix YAML syntax highlight + remove trailing whitespace (ifdattic) - `2b7e0f6 `_ #3497 Fix highlighting (WouterJ) -- `2746067 `_ #3472 Fixed `````versionadded````` inconsistencies in Symfony 2.5+ (danielcsgomes) - `a535ae0 `_ #3471 Fixed `````versionadded````` inconsistencies in Symfony 2.3 (danielcsgomes) - `f077a8e `_ #3465 change wording in versionadded example to be consistent with what we use... (xabbuh) - `f9f7548 `_ #3462 Replace ... with etc (ifdattic) @@ -2156,4 +1670,3 @@ Minor Documentation Changes - `7c5a914 `_ #3369 Indicate that Group Sequence Providers can use YAML (karptonite) - `1e0311e `_ #3416 add empty_data option where required option is used (xabbuh) - `2be3f52 `_ #3422 [Cookbook][Custom Authentication Provider] add a note of warning for when forbidding anonymous users (cordoval) -- `e255de9 `_ #3429 [Reference][Form Types] Document "with_minutes" time/datetime option (bicpi) diff --git a/components/asset/index.rst b/components/asset/index.rst deleted file mode 100644 index 14d04b7eb6f..00000000000 --- a/components/asset/index.rst +++ /dev/null @@ -1,7 +0,0 @@ -Asset -===== - -.. toctree:: - :maxdepth: 2 - - introduction diff --git a/components/asset/introduction.rst b/components/asset/introduction.rst deleted file mode 100644 index 9c72f9342d5..00000000000 --- a/components/asset/introduction.rst +++ /dev/null @@ -1,324 +0,0 @@ -.. index:: - single: Asset - single: Components; Asset - -The Asset Component -=================== - - The Asset component manages URL generation and versioning of web assets such - as CSS stylesheets, JavaScript files and image files. - -In the past, it was common for web applications to hardcode URLs of web assets. -For example: - -.. code-block:: html - - - - - - - -This practice is no longer recommended unless the web application is extremely -simple. Hardcoding URLs can be a disadvantage because: - -* **Templates get verbose**: you have to write the full path for each - asset. When using the Asset component, you can group assets in packages to - avoid repeating the common part of their path; -* **Versioning is difficult**: it has to be custom managed for each - application. Adding a version (e.g. ``main.css?v=5``) to the asset URLs - is essential for some applications because it allows you to control how - the assets are cached. The Asset component allows you to define different - versioning strategies for each package; -* **Moving assets location** is cumbersome and error-prone: it requires you to - carefully update the URLs of all assets included in all templates. The Asset - component allows to move assets effortlessly just by changing the base path - value associated with the package of assets; -* **It's nearly impossible to use multiple CDNs**: this technique requires - you to change the URL of the asset randomly for each request. The Asset component - provides out-of-the-box support for any number of multiple CDNs, both regular - (``http://``) and secure (``https://``). - -Installation ------------- - -You can install the component in two different ways: - -* :doc:`Install it via Composer ` (``symfony/asset`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/asset). - -Usage ------ - -Asset Packages -~~~~~~~~~~~~~~ - -The Asset component manages assets through packages. A package groups all the -assets which share the same properties: versioning strategy, base path, CDN hosts, -etc. In the following basic example, a package is created to manage assets without -any versioning:: - - use Symfony\Component\Asset\Package; - use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy; - - $package = new Package(new EmptyVersionStrategy()); - - echo $package->getUrl('/image.png'); - // result: /image.png - -Packages implement :class:`Symfony\\Component\\Asset\\PackageInterface`, -which defines the following two methods: - -:method:`Symfony\\Component\\Asset\\PackageInterface::getVersion` - Returns the asset version for an asset. - -:method:`Symfony\\Component\\Asset\\PackageInterface::getUrl` - Returns an absolute or root-relative public path. - -With a package, you can: - -A) :ref:`version the assets `; -B) set a :ref:`common base path ` (e.g. ``/css``) - for the assets; -C) :ref:`configure a CDN ` for the assets - -.. _component-assets-versioning: - -Versioned Assets -~~~~~~~~~~~~~~~~ - -One of the main features of the Asset component is the ability to manage -the versioning of the application's assets. Asset versions are commonly used -to control how these assets are cached. - -Instead of relying on a simple version mechanism, the Asset component allows -you to define advanced versioning strategies via PHP classes. The two built-in -strategies are the :class:`Symfony\\Component\\Asset\\VersionStrategy\\EmptyVersionStrategy`, -which doesn't add any version to the asset and :class:`Symfony\\Component\\Asset\\VersionStrategy\\StaticVersionStrategy`, -which allows you to set the version with a format string. - -In this example, the ``StaticVersionStrategy`` is used to append the ``v1`` -suffix to any asset path:: - - use Symfony\Component\Asset\Package; - use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy; - - $package = new Package(new StaticVersionStrategy('v1')); - - echo $package->getUrl('/image.png'); - // result: /image.png?v1 - -In case you want to modify the version format, pass a sprintf-compatible format -string as the second argument of the ``StaticVersionStrategy`` constructor:: - - // put the 'version' word before the version value - $package = new Package(new StaticVersionStrategy('v1', '%s?version=%s')); - - echo $package->getUrl('/image.png'); - // result: /image.png?version=v1 - - // put the asset version before its path - $package = new Package(new StaticVersionStrategy('v1', '%2$s/%1$s')); - - echo $package->getUrl('/image.png'); - // result: /v1/image.png - -Custom Version Strategies -......................... - -Use the :class:`Symfony\\Component\\Asset\\VersionStrategy\\VersionStrategyInterface` -to define your own versioning strategy. For example, your application may need -to append the current date to all its web assets in order to bust the cache -every day:: - - use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface; - - class DateVersionStrategy implements VersionStrategyInterface - { - private $version; - - public function __construct() - { - $this->version = date('Ymd'); - } - - public function getVersion($path) - { - return $this->version; - } - - public function applyVersion($path) - { - return sprintf('%s?v=%s', $path, $this->getVersion($path)); - } - } - -.. _component-assets-path-package: - -Grouped Assets -~~~~~~~~~~~~~~ - -Often, many assets live under a common path (e.g. ``/static/images``). If -that's your case, replace the default :class:`Symfony\\Component\\Asset\\Package` -class with :class:`Symfony\\Component\\Asset\\PathPackage` to avoid repeating -that path over and over again:: - - use Symfony\Component\Asset\PathPackage; - // ... - - $package = new PathPackage('/static/images', new StaticVersionStrategy('v1')); - - echo $package->getUrl('/logo.png'); - // result: /static/images/logo.png?v1 - -Request Context Aware Assets -............................ - -If you are also using the :doc:`HttpFoundation ` -component in your project (for instance, in a Symfony application), the ``PathPackage`` -class can take into account the context of the current request:: - - use Symfony\Component\Asset\PathPackage; - use Symfony\Component\Asset\Context\RequestStackContext; - // ... - - $package = new PathPackage( - '/static/images', - new StaticVersionStrategy('v1'), - new RequestStackContext($requestStack) - ); - - echo $package->getUrl('/logo.png'); - // result: /somewhere/static/images/logo.png?v1 - -Now that the request context is set, the ``PathPackage`` will prepend the -current request base URL. So, for example, if your entire site is hosted under -the ``/somewhere`` directory of your web server root directory and the configured -base path is ``/static/images``, all paths will be prefixed with -``/somewhere/static/images``. - -.. _component-assets-cdn: - -Absolute Assets and CDNs -~~~~~~~~~~~~~~~~~~~~~~~~ - -Applications that host their assets on different domains and CDNs (*Content -Delivery Networks*) should use the :class:`Symfony\\Component\\Asset\\UrlPackage` -class to generate absolute URLs for their assets:: - - use Symfony\Component\Asset\UrlPackage; - // ... - - $package = new UrlPackage( - 'http://static.example.com/images/', - new StaticVersionStrategy('v1') - ); - - echo $package->getUrl('/logo.png'); - // result: http://static.example.com/images/logo.png?v1 - -You can also pass a schema-agnostic URL:: - - use Symfony\Component\Asset\UrlPackage; - // ... - - $package = new UrlPackage( - '//static.example.com/images/', - new StaticVersionStrategy('v1') - ); - - echo $package->getUrl('/logo.png'); - // result: //static.example.com/images/logo.png?v1 - -This is useful because assets will automatically be requested via HTTPS if -a visitor is viewing your site in https. Just make sure that your CDN host -supports https. - -In case you serve assets from more than one domain to improve application -performance, pass an array of URLs as the first argument to the ``UrlPackage`` -constructor:: - - use Symfony\Component\Asset\UrlPackage; - // ... - - $urls = array( - '//static1.example.com/images/', - '//static2.example.com/images/', - ); - $package = new UrlPackage($urls, new StaticVersionStrategy('v1')); - - echo $package->getUrl('/logo.png'); - // result: http://static1.example.com/images/logo.png?v1 - echo $package->getUrl('/icon.png'); - // result: http://static2.example.com/images/icon.png?v1 - -For each asset, one of the URLs will be randomly used. But, the selection -is deterministic, meaning that each asset will be always served by the same -domain. This behavior simplifies the management of HTTP cache. - -Request Context Aware Assets -............................ - -Similarly to application-relative assets, absolute assets can also take into -account the context of the current request. In this case, only the request -scheme is considered, in order to select the appropriate base URL (HTTPs or -protocol-relative URLs for HTTPs requests, any base URL for HTTP requests):: - - use Symfony\Component\Asset\UrlPackage; - use Symfony\Component\Asset\Context\RequestStackContext; - // ... - - $package = new UrlPackage( - array('http://example.com/', 'https://example.com/'), - new StaticVersionStrategy('v1'), - new RequestStackContext($requestStack) - ); - - echo $package->getUrl('/logo.png'); - // assuming the RequestStackContext says that we are on a secure host - // result: https://example.com/logo.png?v1 - -Named Packages -~~~~~~~~~~~~~~ - -Applications that manage lots of different assets may need to group them in -packages with the same versioning strategy and base path. The Asset component -includes a :class:`Symfony\\Component\\Asset\\Packages` class to simplify -management of several packages. - -In the following example, all packages use the same versioning strategy, but -they all have different base paths:: - - use Symfony\Component\Asset\Package; - use Symfony\Component\Asset\PathPackage; - use Symfony\Component\Asset\UrlPackage; - use Symfony\Component\Asset\Packages; - // ... - - $versionStrategy = new StaticVersionStrategy('v1'); - - $defaultPackage = new Package($versionStrategy); - - $namedPackages = array( - 'img' => new UrlPackage('http://img.example.com/', $versionStrategy), - 'doc' => new PathPackage('/somewhere/deep/for/documents', $versionStrategy), - ); - - $packages = new Packages($defaultPackage, $namedPackages) - -The ``Packages`` class allows to define a default package, which will be applied -to assets that don't define the name of package to use. In addition, this -application defines a package named ``img`` to serve images from an external -domain and a ``doc`` package to avoid repeating long paths when linking to a -document inside a template:: - - echo $packages->getUrl('/main.css'); - // result: /main.css?v1 - - echo $packages->getUrl('/logo.png', 'img'); - // result: http://img.example.com/logo.png?v1 - - echo $packages->getUrl('/resume.pdf', 'doc'); - // result: /somewhere/deep/for/documents/resume.pdf?v1 - -.. _Packagist: https://packagist.org/packages/symfony/asset diff --git a/components/class_loader/cache_class_loader.rst b/components/class_loader/cache_class_loader.rst index ff7aaba0885..46622eb4e3d 100644 --- a/components/class_loader/cache_class_loader.rst +++ b/components/class_loader/cache_class_loader.rst @@ -26,6 +26,9 @@ for a class. ApcClassLoader -------------- +.. versionadded:: 2.1 + The ``ApcClassLoader`` class was introduced in Symfony 2.1. + ``ApcClassLoader`` wraps an existing class loader and caches calls to its ``findFile()`` method using `APC`_:: @@ -46,6 +49,9 @@ ApcClassLoader XcacheClassLoader ----------------- +.. versionadded:: 2.1 + The ``XcacheClassLoader`` class was introduced in Symfony 2.1. + ``XcacheClassLoader`` uses `XCache`_ to cache a class loader. Registering it is straightforward:: diff --git a/components/class_loader/class_loader.rst b/components/class_loader/class_loader.rst index 2d0e64978d1..9e477795c10 100644 --- a/components/class_loader/class_loader.rst +++ b/components/class_loader/class_loader.rst @@ -4,6 +4,9 @@ The PSR-0 Class Loader ====================== +.. versionadded:: 2.1 + The ``ClassLoader`` class was introduced in Symfony 2.1. + If your classes and third-party libraries follow the `PSR-0`_ standard, you can use the :class:`Symfony\\Component\\ClassLoader\\ClassLoader` class to load all of your project's classes. @@ -12,7 +15,8 @@ to load all of your project's classes. You can use both the ``ApcClassLoader`` and the ``XcacheClassLoader`` to :doc:`cache ` a ``ClassLoader`` - instance. + instance or the ``DebugClassLoader`` to :doc:`debug ` + it. Usage ----- diff --git a/components/class_loader/debug_class_loader.rst b/components/class_loader/debug_class_loader.rst index 06dfce69716..1f08128749f 100644 --- a/components/class_loader/debug_class_loader.rst +++ b/components/class_loader/debug_class_loader.rst @@ -1,8 +1,20 @@ +.. index:: + single: ClassLoader; DebugClassLoader + Debugging a Class Loader ======================== -.. caution:: +.. versionadded:: 2.1 + The ``DebugClassLoader`` class was introduced in Symfony 2.1. + +The :class:`Symfony\\Component\\ClassLoader\\DebugClassLoader` attempts +to throw more helpful exceptions when a class isn't found by the registered +autoloaders. All autoloaders that implement a ``findFile()`` method are +replaced with a ``DebugClassLoader`` wrapper. + +Using the ``DebugClassLoader`` is as easy as calling its static +:method:`Symfony\\Component\\ClassLoader\\DebugClassLoader::enable` method:: + + use Symfony\Component\ClassLoader\DebugClassLoader; - The ``DebugClassLoader`` from the ClassLoader component was deprecated - in Symfony 2.5 and removed in Symfony 3.0. Use the - :doc:`DebugClassLoader provided by the Debug component `. + DebugClassLoader::enable(); diff --git a/components/class_loader/index.rst b/components/class_loader/index.rst index 5215b57291d..864bf77d734 100644 --- a/components/class_loader/index.rst +++ b/components/class_loader/index.rst @@ -6,12 +6,7 @@ ClassLoader introduction class_loader - psr4_class_loader map_class_loader cache_class_loader - class_map_generator - -.. toctree:: - :hidden: - debug_class_loader + class_map_generator diff --git a/components/class_loader/introduction.rst b/components/class_loader/introduction.rst index 0c9ae90402b..e5e3f581f56 100644 --- a/components/class_loader/introduction.rst +++ b/components/class_loader/introduction.rst @@ -12,26 +12,21 @@ Usage Whenever you reference a class that has not been required or included yet, PHP uses the `autoloading mechanism`_ to delegate the loading of a file -defining the class. Symfony provides three autoloaders, which are able to +defining the class. Symfony provides two autoloaders, which are able to load your classes: * :doc:`/components/class_loader/class_loader`: loads classes that follow the `PSR-0`_ class naming standard; -* :doc:`/components/class_loader/psr4_class_loader`: loads classes that follow - the `PSR-4` class naming standard; - * :doc:`/components/class_loader/map_class_loader`: loads classes using a static map from class name to file path. -Additionally, the Symfony ClassLoader component ships with a wrapper class -which makes it possible -:doc:`to cache the results of a class loader `. +Additionally, the Symfony ClassLoader component ships with a set of wrapper +classes which can be used to add additional functionality on top of existing +autoloaders: -When using the :doc:`Debug component `, you -can also use a special :doc:`DebugClassLoader ` -that eases debugging by throwing more helpful exceptions when a class could -not be found by a class loader. +* :doc:`/components/class_loader/cache_class_loader` +* :doc:`/components/class_loader/debug_class_loader` Installation ------------ diff --git a/components/class_loader/psr4_class_loader.rst b/components/class_loader/psr4_class_loader.rst deleted file mode 100644 index b593e174027..00000000000 --- a/components/class_loader/psr4_class_loader.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. index:: - single: ClassLoader; PSR-4 Class Loader - -The PSR-4 Class Loader -====================== - -Libraries that follow the `PSR-4`_ standard can be loaded with the ``Psr4ClassLoader``. - -.. note:: - - If you manage your dependencies via Composer, you get a PSR-4 compatible - autoloader out of the box. Use this loader in environments where Composer - is not available. - -.. tip:: - - All Symfony components follow PSR-4. - -Usage ------ - -The following example demonstrates how you can use the -:class:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader` autoloader to use -Symfony's Yaml component. Imagine, you downloaded both the ClassLoader and -Yaml component as ZIP packages and unpacked them to a ``libs`` directory. -The directory structure will look like this: - -.. code-block:: text - - libs/ - ClassLoader/ - Psr4ClassLoader.php - ... - Yaml/ - Yaml.php - ... - config.yml - demo.php - -In ``demo.php`` you are going to parse the ``config.yml`` file. To do that, you -first need to configure the ``Psr4ClassLoader``: - -.. code-block:: php - - use Symfony\Component\ClassLoader\Psr4ClassLoader; - use Symfony\Component\Yaml\Yaml; - - require __DIR__.'/lib/ClassLoader/Psr4ClassLoader.php'; - - $loader = new Psr4ClassLoader(); - $loader->addPrefix('Symfony\\Component\\Yaml\\', __DIR__.'/lib/Yaml'); - $loader->register(); - - $data = Yaml::parse(file_get_contents(__DIR__.'/config.yml')); - -First of all, the class loader is loaded manually using a ``require`` -statement, since there is no autoload mechanism yet. With the -:method:`Symfony\\Component\\ClassLoader\\Psr4ClassLoader::addPrefix` call, you -tell the class loader where to look for classes with the -``Symfony\Component\Yaml\`` namespace prefix. After registering the autoloader, -the Yaml component is ready to be used. - -.. _PSR-4: http://www.php-fig.org/psr/psr-4/ diff --git a/components/config/definition.rst b/components/config/definition.rst index cb799da44d0..e9d8787fc76 100644 --- a/components/config/definition.rst +++ b/components/config/definition.rst @@ -102,9 +102,10 @@ node definition. Node types are available for: * scalar (generic type that includes booleans, strings, integers, floats and ``null``) * boolean -* integer -* float -* enum (similar to scalar, but it only allows a finite set of values) +* integer (new in 2.2) +* float (new in 2.2) +* enum (new in 2.1) (similar to scalar, but it only allows a finite set + of values) * array * variable (no validation) @@ -114,6 +115,9 @@ and are created with ``node($name, $type)`` or their associated shortcut Numeric Node Constraints ~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.2 + The numeric (float and integer) nodes were introduced in Symfony 2.2. + Numeric nodes (float and integer) provide two extra constraints - :method:`Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition::min` and :method:`Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition::max` @@ -136,6 +140,9 @@ and :method:`Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinit Enum Nodes ~~~~~~~~~~ +.. versionadded:: 2.1 + The enum node was introduced in Symfony 2.1. + Enum nodes provide a constraint to match the given input against a set of values:: @@ -439,16 +446,13 @@ In YAML you may have: # This value is only used for the search results page. entries_per_page: 25 -and in XML: - -.. code-block:: xml - - - - Optional Sections ----------------- +.. versionadded:: 2.2 + The ``canBeEnabled`` and ``canBeDisabled`` methods were introduced in + Symfony 2.2. + If you have entire sections which are optional and can be enabled/disabled, you can take advantage of the shortcut :method:`Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition::canBeEnabled` diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst deleted file mode 100644 index adbf31a4ae3..00000000000 --- a/components/console/changing_default_command.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. index:: - single: Console; Changing the Default Command - -Changing the Default Command -============================ - -The Console component will always run the ``ListCommand`` when no command name is -passed. In order to change the default command you just need to pass the command -name to the ``setDefaultCommand`` method:: - - namespace Acme\Console\Command; - - use Symfony\Component\Console\Command\Command; - use Symfony\Component\Console\Input\InputInterface; - use Symfony\Component\Console\Output\OutputInterface; - - class HelloWorldCommand extends Command - { - protected function configure() - { - $this->setName('hello:world') - ->setDescription('Outputs \'Hello World\''); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $output->writeln('Hello World'); - } - } - -Executing the application and changing the default Command:: - - // application.php - - use Acme\Console\Command\HelloWorldCommand; - use Symfony\Component\Console\Application; - - $command = new HelloWorldCommand(); - $application = new Application(); - $application->add($command); - $application->setDefaultCommand($command->getName()); - $application->run(); - -Test the new default console command by running the following: - -.. code-block:: bash - - $ php application.php - -This will print the following to the command line: - -.. code-block:: text - - Hello World - -.. tip:: - - This feature has a limitation: you cannot use it with any Command arguments. - -Learn More! ------------ - -* :doc:`/components/console/single_command_tool` diff --git a/components/console/events.rst b/components/console/events.rst index 9405635ebeb..25cd54e882a 100644 --- a/components/console/events.rst +++ b/components/console/events.rst @@ -4,6 +4,9 @@ Using Events ============ +.. versionadded:: 2.3 + Console events were introduced in Symfony 2.3. + The Application class of the Console component allows you to optionally hook into the lifecycle of a console application via events. Instead of reinventing the wheel, it uses the Symfony EventDispatcher component to do the work:: @@ -53,36 +56,6 @@ dispatched. Listeners receive a $application = $command->getApplication(); }); -Disable Commands inside Listeners -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using the -:method:`Symfony\\Component\\Console\\Event\\ConsoleCommandEvent::disableCommand` -method, you can disable a command inside a listener. The application -will then *not* execute the command, but instead will return the code ``113`` -(defined in ``ConsoleCommandEvent::RETURN_CODE_DISABLED``). This code is one -of the `reserved exit codes`_ for console commands that conform with the -C/C++ standard.:: - - use Symfony\Component\Console\Event\ConsoleCommandEvent; - use Symfony\Component\Console\ConsoleEvents; - - $dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) { - // get the command to be executed - $command = $event->getCommand(); - - // ... check if the command can be executed - - // disable the command, this will result in the command being skipped - // and code 113 being returned from the Application - $event->disableCommand(); - - // it is possible to enable the command in a later listener - if (!$event->commandShouldRun()) { - $event->enableCommand(); - } - }); - The ``ConsoleEvents::TERMINATE`` Event -------------------------------------- @@ -150,5 +123,3 @@ Listeners receive a // change the exception to another one $event->setException(new \LogicException('Caught exception', $exitCode, $event->getException())); }); - -.. _`reserved exit codes`: http://www.tldp.org/LDP/abs/html/exitcodes.html diff --git a/components/console/helpers/debug_formatter.rst b/components/console/helpers/debug_formatter.rst deleted file mode 100644 index d48b6a9e060..00000000000 --- a/components/console/helpers/debug_formatter.rst +++ /dev/null @@ -1,142 +0,0 @@ -.. index:: - single: Console Helpers; DebugFormatter Helper - -Debug Formatter Helper -====================== - -The :class:`Symfony\\Component\\Console\\Helper\\DebugFormatterHelper` provides -functions to output debug information when running an external program, for -instance a process or HTTP request. For example, if you used it to output -the results of running ``ls -la`` on a UNIX system, it might output something -like this: - -.. image:: /images/components/console/debug_formatter.png - :align: center - -Using the debug_formatter -------------------------- - -The formatter is included in the default helper set and you can get it by -calling :method:`Symfony\\Component\\Console\\Command\\Command::getHelper`:: - - $debugFormatter = $this->getHelper('debug_formatter'); - -The formatter accepts strings and returns a formatted string, which you then -output to the console (or even log the information or do anything else). - -All methods of this helper have an identifier as the first argument. This is a -unique value for each program. This way, the helper can debug information for -multiple programs at the same time. When using the -:doc:`Process component `, you probably want to use -:phpfunction:`spl_object_hash`. - -.. tip:: - - This information is often too verbose to be shown by default. You can use - :ref:`verbosity levels ` to only show it when in - debugging mode (``-vvv``). - -Starting a Program ------------------- - -As soon as you start a program, you can use -:method:`Symfony\\Component\\Console\\Helper\\DebugFormatterHelper::start` to -display information that the program is started:: - - // ... - $process = new Process(...); - - $output->writeln($debugFormatter->start( - spl_object_hash($process), - 'Some process description' - )); - - $process->run(); - -This will output: - -.. code-block:: text - - RUN Some process description - -You can tweak the prefix using the third argument:: - - $output->writeln($debugFormatter->start( - spl_object_hash($process), - 'Some process description', - 'STARTED' - )); - // will output: - // STARTED Some process description - -Output Progress Information ---------------------------- - -Some programs give output while they are running. This information can be shown -using -:method:`Symfony\\Component\\Console\\Helper\\DebugFormatterHelper::progress`:: - - use Symfony\Component\Process\Process; - - // ... - $process = new Process(...); - - $process->run(function ($type, $buffer) use ($output, $debugFormatter, $process) { - $output->writeln( - $debugFormatter->progress( - spl_object_hash($process), - $buffer, - Process::ERR === $type - ) - ); - }); - // ... - -In case of success, this will output: - -.. code-block:: text - - OUT The output of the process - -And this in case of failure: - -.. code-block:: text - - ERR The output of the process - -The third argument is a boolean which tells the function if the output is error -output or not. When ``true``, the output is considered error output. - -The fourth and fifth argument allow you to override the prefix for the normal -output and error output respectively. - -Stopping a Program ------------------- - -When a program is stopped, you can use -:method:`Symfony\\Component\\Console\\Helper\\DebugFormatterHelper::stop` to -notify this to the users:: - - // ... - $output->writeln( - $debugFormatter->stop( - spl_object_hash($process), - 'Some command description', - $process->isSuccessfull() - ) - ); - -This will output: - -.. code-block:: text - - RES Some command description - -In case of failure, this will be in red and in case of success it will be green. - -Using multiple Programs ------------------------ - -As said before, you can also use the helper to display more programs at the -same time. Information about different programs will be shown in different -colors, to make it clear which output belongs to which command. diff --git a/components/console/helpers/dialoghelper.rst b/components/console/helpers/dialoghelper.rst index 8618ffcba17..c28588796ff 100644 --- a/components/console/helpers/dialoghelper.rst +++ b/components/console/helpers/dialoghelper.rst @@ -4,9 +4,294 @@ Dialog Helper ============= +The :class:`Symfony\\Component\\Console\\Helper\\DialogHelper` provides +functions to ask the user for more information. It is included in the default +helper set, which you can get by calling +:method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: + + $dialog = $this->getHelper('dialog'); + +All the methods inside the Dialog Helper have an +:class:`Symfony\\Component\\Console\\Output\\OutputInterface` as the first +argument, the question as the second argument and the default value as the last +argument. + +Asking the User for Confirmation +-------------------------------- + +Suppose you want to confirm an action before actually executing it. Add +the following to your command:: + + // ... + if (!$dialog->askConfirmation( + $output, + 'Continue with this action?', + false + )) { + return; + } + +In this case, the user will be asked "Continue with this action?", and will +return ``true`` if the user answers with ``y`` or ``false`` if the user answers +with ``n``. The third argument to +:method:`Symfony\\Component\\Console\\Helper\\DialogHelper::askConfirmation` +is the default value to return if the user doesn't enter any input. Any other +input will ask the same question again. + +Asking the User for Information +------------------------------- + +You can also ask question with more than a simple yes/no answer. For instance, +if you want to know a bundle name, you can add this to your command:: + + // ... + $bundle = $dialog->ask( + $output, + 'Please enter the name of the bundle', + 'AcmeDemoBundle' + ); + +The user will be asked "Please enter the name of the bundle". They can type +some name which will be returned by the +:method:`Symfony\\Component\\Console\\Helper\\DialogHelper::ask` method. +If they leave it empty, the default value (AcmeDemoBundle here) is returned. + +Autocompletion +~~~~~~~~~~~~~~ + +.. versionadded:: 2.2 + Autocompletion for questions was introduced in Symfony 2.2. + +You can also specify an array of potential answers for a given question. These +will be autocompleted as the user types:: + + $dialog = $this->getHelper('dialog'); + $bundleNames = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle'); + $name = $dialog->ask( + $output, + 'Please enter the name of a bundle', + 'FooBundle', + $bundleNames + ); + +Hiding the User's Response +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.2 + The ``askHiddenResponse`` method was introduced in Symfony 2.2. + +You can also ask a question and hide the response. This is particularly +convenient for passwords:: + + $dialog = $this->getHelper('dialog'); + $password = $dialog->askHiddenResponse( + $output, + 'What is the database password?', + false + ); + .. caution:: - The Dialog Helper was deprecated in Symfony 2.5 and removed in - Symfony 3.0. You should now use the - :doc:`Question Helper ` instead, - which is simpler to use. + When you ask for a hidden response, Symfony will use either a binary, change + stty mode or use another trick to hide the response. If none is available, + it will fallback and allow the response to be visible unless you pass ``false`` + as the third argument like in the example above. In this case, a ``RuntimeException`` + would be thrown. + +Validating the Answer +--------------------- + +You can even validate the answer. For instance, in the last example you asked +for the bundle name. Following the Symfony naming conventions, it should +be suffixed with ``Bundle``. You can validate that by using the +:method:`Symfony\\Component\\Console\\Helper\\DialogHelper::askAndValidate` +method:: + + // ... + $bundle = $dialog->askAndValidate( + $output, + 'Please enter the name of the bundle', + function ($answer) { + if ('Bundle' !== substr($answer, -6)) { + throw new \RuntimeException( + 'The name of the bundle should be suffixed with \'Bundle\'' + ); + } + + return $answer; + }, + false, + 'AcmeDemoBundle' + ); + +This methods has 2 new arguments, the full signature is:: + + askAndValidate( + OutputInterface $output, + string|array $question, + callback $validator, + integer $attempts = false, + string $default = null, + array $autocomplete = null + ) + +The ``$validator`` is a callback which handles the validation. It should +throw an exception if there is something wrong. The exception message is displayed +in the console, so it is a good practice to put some useful information in it. The callback +function should also return the value of the user's input if the validation was successful. + +You can set the max number of times to ask in the ``$attempts`` argument. +If you reach this max number it will use the default value. +Using ``false`` means the amount of attempts is infinite. +The user will be asked as long as they provide an invalid answer and will only +be able to proceed if their input is valid. + +Validating a Hidden Response +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.2 + The ``askHiddenResponseAndValidate`` method was introduced in Symfony 2.2. + +You can also ask and validate a hidden response:: + + $dialog = $this->getHelper('dialog'); + + $validator = function ($value) { + if ('' === trim($value)) { + throw new \Exception('The password can not be empty'); + } + + return $value; + }; + + $password = $dialog->askHiddenResponseAndValidate( + $output, + 'Please enter your password', + $validator, + 20, + false + ); + +If you want to allow the response to be visible if it cannot be hidden for +some reason, pass true as the fifth argument. + +Let the User Choose from a List of Answers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.2 + The :method:`Symfony\\Component\\Console\\Helper\\DialogHelper::select` method + was introduced in Symfony 2.2. + +If you have a predefined set of answers the user can choose from, you +could use the ``ask`` method described above or, to make sure the user +provided a correct answer, the ``askAndValidate`` method. Both have +the disadvantage that you need to handle incorrect values yourself. + +Instead, you can use the +:method:`Symfony\\Component\\Console\\Helper\\DialogHelper::select` +method, which makes sure that the user can only enter a valid string +from a predefined list:: + + $dialog = $this->getHelper('dialog'); + $colors = array('red', 'blue', 'yellow'); + + $color = $dialog->select( + $output, + 'Please select your favorite color (default to red)', + $colors, + 0 + ); + $output->writeln('You have just selected: ' . $colors[$color]); + + // ... do something with the color + +The option which should be selected by default is provided with the fourth +argument. The default is ``null``, which means that no option is the default one. + +If the user enters an invalid string, an error message is shown and the user +is asked to provide the answer another time, until they enter a valid string +or the maximum attempts is reached (which you can define in the fifth +argument). The default value for the attempts is ``false``, which means infinite +attempts. You can define your own error message in the sixth argument. + +.. versionadded:: 2.3 + Multiselect support was introduced in Symfony 2.3. + +Multiple Choices +................ + +Sometimes, multiple answers can be given. The DialogHelper provides this +feature using comma separated values. This is disabled by default, to enable +this set the seventh argument to ``true``:: + + // ... + + $selected = $dialog->select( + $output, + 'Please select your favorite color (default to red)', + $colors, + 0, + false, + 'Value "%s" is invalid', + true // enable multiselect + ); + + $selectedColors = array_map(function ($c) use ($colors) { + return $colors[$c]; + }, $selected); + + $output->writeln( + 'You have just selected: ' . implode(', ', $selectedColors) + ); + +Now, when the user enters ``1,2``, the result will be: +``You have just selected: blue, yellow``. + +Testing a Command which Expects Input +------------------------------------- + +If you want to write a unit test for a command which expects some kind of input +from the command line, you need to overwrite the HelperSet used by the command:: + + use Symfony\Component\Console\Application; + use Symfony\Component\Console\Helper\DialogHelper; + use Symfony\Component\Console\Helper\HelperSet; + use Symfony\Component\Console\Tester\CommandTester; + + // ... + public function testExecute() + { + // ... + $application = new Application(); + $application->add(new MyCommand()); + $command = $application->find('my:command:name'); + $commandTester = new CommandTester($command); + + $dialog = $command->getHelper('dialog'); + $dialog->setInputStream($this->getInputStream("Test\n")); + // Equals to a user inputting "Test" and hitting ENTER + // If you need to enter a confirmation, "yes\n" will work + + $commandTester->execute(array('command' => $command->getName())); + + // $this->assertRegExp('/.../', $commandTester->getDisplay()); + } + + protected function getInputStream($input) + { + $stream = fopen('php://memory', 'r+', false); + fputs($stream, $input); + rewind($stream); + + return $stream; + } + +By setting the input stream of the ``DialogHelper``, you imitate what the +console would do internally with all user input through the cli. This way +you can test any user interaction (even complex ones) by passing an appropriate +input stream. + +.. seealso:: + + You find more information about testing commands in the console component + docs about :ref:`testing console commands `. diff --git a/components/console/helpers/index.rst b/components/console/helpers/index.rst index bf51dc40c92..1c95bc47057 100644 --- a/components/console/helpers/index.rst +++ b/components/console/helpers/index.rst @@ -9,13 +9,8 @@ The Console Helpers dialoghelper formatterhelper - processhelper - progressbar progresshelper - questionhelper - table tablehelper - debug_formatter The Console component comes with some useful helpers. These helpers contain function to ease some common tasks. diff --git a/components/console/helpers/map.rst.inc b/components/console/helpers/map.rst.inc index 68e1e722a87..60b32c03975 100644 --- a/components/console/helpers/map.rst.inc +++ b/components/console/helpers/map.rst.inc @@ -1,6 +1,4 @@ +* :doc:`/components/console/helpers/dialoghelper` * :doc:`/components/console/helpers/formatterhelper` -* :doc:`/components/console/helpers/processhelper` -* :doc:`/components/console/helpers/progressbar` -* :doc:`/components/console/helpers/questionhelper` -* :doc:`/components/console/helpers/table` -* :doc:`/components/console/helpers/debug_formatter` +* :doc:`/components/console/helpers/progresshelper` +* :doc:`/components/console/helpers/tablehelper` diff --git a/components/console/helpers/processhelper.rst b/components/console/helpers/processhelper.rst deleted file mode 100644 index 6a4f7c6f6b5..00000000000 --- a/components/console/helpers/processhelper.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. index:: - single: Console Helpers; Process Helper - -Process Helper -============== - -The Process Helper shows processes as they're running and reports -useful information about process status. - -To display process details, use the :class:`Symfony\\Component\\Console\\Helper\\ProcessHelper` -and run your command with verbosity. For example, running the following code with -a very verbose verbosity (e.g. -vv):: - - use Symfony\Component\Process\ProcessBuilder; - - $helper = $this->getHelper('process'); - $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); - - $helper->run($output, $process); - -will result in this output: - -.. image:: /images/components/console/process-helper-verbose.png - -It will result in more detailed output with debug verbosity (e.g. ``-vvv``): - -.. image:: /images/components/console/process-helper-debug.png - -In case the process fails, debugging is easier: - -.. image:: /images/components/console/process-helper-error-debug.png - -Arguments ---------- - -There are three ways to use the process helper: - -* Using a command line string:: - - // ... - $helper->run($output, 'figlet Symfony'); - -* An array of arguments:: - - // ... - $helper->run($output, array('figlet', 'Symfony')); - - .. note:: - - When running the helper against an array of arguments, be aware that - these will be automatically escaped. - -* Passing a :class:`Symfony\\Component\\Process\\Process` instance:: - - use Symfony\Component\Process\ProcessBuilder; - - // ... - $process = ProcessBuilder::create(array('figlet', 'Symfony'))->getProcess(); - - $helper->run($output, $process); - -Customized Display ------------------- - -You can display a customized error message using the third argument of the -:method:`Symfony\\Component\\Console\\Helper\\ProcessHelper::run` method:: - - $helper->run($output, $process, 'The process failed :('); - -A custom process callback can be passed as the fourth argument. Refer to the -:doc:`Process Component ` for callback documentation:: - - use Symfony\Component\Process\Process; - - $helper->run($output, $process, 'The process failed :(', function ($type, $data) { - if (Process::ERR === $type) { - // ... do something with the stderr output - } else { - // ... do something with the stdout - } - }); diff --git a/components/console/helpers/progressbar.rst b/components/console/helpers/progressbar.rst deleted file mode 100644 index 0e73aa91231..00000000000 --- a/components/console/helpers/progressbar.rst +++ /dev/null @@ -1,323 +0,0 @@ -.. index:: - single: Console Helpers; Progress Bar - -Progress Bar -============ - -When executing longer-running commands, it may be helpful to show progress -information, which updates as your command runs: - -.. image:: /images/components/console/progressbar.gif - -To display progress details, use the -:class:`Symfony\\Component\\Console\\Helper\\ProgressBar`, pass it a total -number of units, and advance the progress as the command executes:: - - use Symfony\Component\Console\Helper\ProgressBar; - - // create a new progress bar (50 units) - $progress = new ProgressBar($output, 50); - - // start and displays the progress bar - $progress->start(); - - $i = 0; - while ($i++ < 50) { - // ... do some work - - // advance the progress bar 1 unit - $progress->advance(); - - // you can also advance the progress bar by more than 1 unit - // $progress->advance(3); - } - - // ensure that the progress bar is at 100% - $progress->finish(); - -Instead of advancing the bar by a number of steps (with the -:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::advance` method), -you can also set the current progress by calling the -:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setProgress` method. - -.. tip:: - - If your platform doesn't support ANSI codes, updates to the progress - bar are added as new lines. To prevent the output from being flooded, - adjust the - :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setRedrawFrequency` - accordingly. By default, when using a ``max``, the redraw frequency - is set to *10%* of your ``max``. - -If you don't know the number of steps in advance, just omit the steps argument -when creating the :class:`Symfony\\Component\\Console\\Helper\\ProgressBar` -instance:: - - $progress = new ProgressBar($output); - -The progress will then be displayed as a throbber: - -.. code-block:: text - - # no max steps (displays it like a throbber) - 0 [>---------------------------] - 5 [----->----------------------] - 5 [============================] - - # max steps defined - 0/3 [>---------------------------] 0% - 1/3 [=========>------------------] 33% - 3/3 [============================] 100% - -Whenever your task is finished, don't forget to call -:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::finish` to ensure -that the progress bar display is refreshed with a 100% completion. - -.. note:: - - If you want to output something while the progress bar is running, - call :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::clear` first. - After you're done, call - :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::display` - to show the progress bar again. - -Customizing the Progress Bar ----------------------------- - -Built-in Formats -~~~~~~~~~~~~~~~~ - -By default, the information rendered on a progress bar depends on the current -level of verbosity of the ``OutputInterface`` instance: - -.. code-block:: text - - # OutputInterface::VERBOSITY_NORMAL (CLI with no verbosity flag) - 0/3 [>---------------------------] 0% - 1/3 [=========>------------------] 33% - 3/3 [============================] 100% - - # OutputInterface::VERBOSITY_VERBOSE (-v) - 0/3 [>---------------------------] 0% 1 sec - 1/3 [=========>------------------] 33% 1 sec - 3/3 [============================] 100% 1 sec - - # OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) - 0/3 [>---------------------------] 0% 1 sec - 1/3 [=========>------------------] 33% 1 sec - 3/3 [============================] 100% 1 sec - - # OutputInterface::VERBOSITY_DEBUG (-vvv) - 0/3 [>---------------------------] 0% 1 sec/1 sec 1.0 MB - 1/3 [=========>------------------] 33% 1 sec/1 sec 1.0 MB - 3/3 [============================] 100% 1 sec/1 sec 1.0 MB - -.. note:: - - If you call a command with the quiet flag (``-q``), the progress bar won't - be displayed. - -Instead of relying on the verbosity mode of the current command, you can also -force a format via ``setFormat()``:: - - $bar->setFormat('verbose'); - -The built-in formats are the following: - -* ``normal`` -* ``verbose`` -* ``very_verbose`` -* ``debug`` - -If you don't set the number of steps for your progress bar, use the ``_nomax`` -variants: - -* ``normal_nomax`` -* ``verbose_nomax`` -* ``very_verbose_nomax`` -* ``debug_nomax`` - -Custom Formats -~~~~~~~~~~~~~~ - -Instead of using the built-in formats, you can also set your own:: - - $bar->setFormat('%bar%'); - -This sets the format to only display the progress bar itself: - -.. code-block:: text - - >--------------------------- - =========>------------------ - ============================ - -A progress bar format is a string that contains specific placeholders (a name -enclosed with the ``%`` character); the placeholders are replaced based on the -current progress of the bar. Here is a list of the built-in placeholders: - -* ``current``: The current step; -* ``max``: The maximum number of steps (or 0 if no max is defined); -* ``bar``: The bar itself; -* ``percent``: The percentage of completion (not available if no max is defined); -* ``elapsed``: The time elapsed since the start of the progress bar; -* ``remaining``: The remaining time to complete the task (not available if no max is defined); -* ``estimated``: The estimated time to complete the task (not available if no max is defined); -* ``memory``: The current memory usage; -* ``message``: The current message attached to the progress bar. - -For instance, here is how you could set the format to be the same as the -``debug`` one:: - - $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%'); - -Notice the ``:6s`` part added to some placeholders? That's how you can tweak -the appearance of the bar (formatting and alignment). The part after the colon -(``:``) is used to set the ``sprintf`` format of the string. - -The ``message`` placeholder is a bit special as you must set the value -yourself:: - - $bar->setMessage('Task starts'); - $bar->start(); - - $bar->setMessage('Task in progress...'); - $bar->advance(); - - // ... - - $bar->setMessage('Task is finished'); - $bar->finish(); - -Instead of setting the format for a given instance of a progress bar, you can -also define global formats:: - - ProgressBar::setFormatDefinition('minimal', 'Progress: %percent%%'); - - $bar = new ProgressBar($output, 3); - $bar->setFormat('minimal'); - -This code defines a new ``minimal`` format that you can then use for your -progress bars: - -.. code-block:: text - - Progress: 0% - Progress: 33% - Progress: 100% - -.. tip:: - - It is almost always better to redefine built-in formats instead of creating - new ones as that allows the display to automatically vary based on the - verbosity flag of the command. - -When defining a new style that contains placeholders that are only available -when the maximum number of steps is known, you should create a ``_nomax`` -variant:: - - ProgressBar::setFormatDefinition('minimal', '%percent%% %remaining%'); - ProgressBar::setFormatDefinition('minimal_nomax', '%percent%%'); - - $bar = new ProgressBar($output); - $bar->setFormat('minimal'); - -When displaying the progress bar, the format will automatically be set to -``minimal_nomax`` if the bar does not have a maximum number of steps like in -the example above. - -.. tip:: - - A format can contain any valid ANSI codes and can also use the - Symfony-specific way to set colors:: - - ProgressBar::setFormatDefinition( - 'minimal', - '%percent%\033[32m%\033[0m %remaining%' - ); - -.. note:: - - A format can span more than one line; that's very useful when you want to - display more contextual information alongside the progress bar (see the - example at the beginning of this article). - -Bar Settings -~~~~~~~~~~~~ - -Amongst the placeholders, ``bar`` is a bit special as all the characters used -to display it can be customized:: - - // the finished part of the bar - $progress->setBarCharacter('='); - - // the unfinished part of the bar - $progress->setEmptyBarCharacter(' '); - - // the progress character - $progress->setProgressCharacter('|'); - - // the bar width - $progress->setBarWidth(50); - -.. caution:: - - For performance reasons, be careful if you set the total number of steps - to a high number. For example, if you're iterating over a large number of - items, consider setting the redraw frequency to a higher value by calling - :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setRedrawFrequency`, - so it updates on only some iterations:: - - $progress = new ProgressBar($output, 50000); - $progress->start(); - - // update every 100 iterations - $progress->setRedrawFrequency(100); - - $i = 0; - while ($i++ < 50000) { - // ... do some work - - $progress->advance(); - } - -Custom Placeholders -~~~~~~~~~~~~~~~~~~~ - -If you want to display some information that depends on the progress bar -display that are not available in the list of built-in placeholders, you can -create your own. Let's see how you can create a ``remaining_steps`` placeholder -that displays the number of remaining steps:: - - ProgressBar::setPlaceholderFormatterDefinition( - 'remaining_steps', - function (ProgressBar $bar, OutputInterface $output) { - return $bar->getMaxSteps() - $bar->getProgress(); - } - ); - -Custom Messages -~~~~~~~~~~~~~~~ - -The ``%message%`` placeholder allows you to specify a custom message to be -displayed with the progress bar. But if you need more than one, just define -your own:: - - $bar->setMessage('Task starts'); - $bar->setMessage('', 'filename'); - $bar->start(); - - $bar->setMessage('Task is in progress...'); - while ($file = array_pop($files)) { - $bar->setMessage($filename, 'filename'); - $bar->advance(); - } - - $bar->setMessage('Task is finished'); - $bar->setMessage('', 'filename'); - $bar->finish(); - -For the ``filename`` to be part of the progress bar, just add the -``%filename%`` placeholder in your format:: - - $bar->setFormat(" %message%\n %current%/%max%\n Working on %filename%"); diff --git a/components/console/helpers/progresshelper.rst b/components/console/helpers/progresshelper.rst index aec5c9b62ea..ee0366dd287 100644 --- a/components/console/helpers/progresshelper.rst +++ b/components/console/helpers/progresshelper.rst @@ -4,9 +4,81 @@ Progress Helper =============== +.. versionadded:: 2.2 + The ``progress`` helper was introduced in Symfony 2.2. + +.. versionadded:: 2.3 + The ``setCurrent`` method was introduced in Symfony 2.3. + +When executing longer-running commands, it may be helpful to show progress +information, which updates as your command runs: + +.. image:: /images/components/console/progress.png + +To display progress details, use the :class:`Symfony\\Component\\Console\\Helper\\ProgressHelper`, +pass it a total number of units, and advance the progress as your command executes:: + + $progress = $this->getHelper('progress'); + + $progress->start($output, 50); + $i = 0; + while ($i++ < 50) { + // ... do some work + + // advance the progress bar 1 unit + $progress->advance(); + } + + $progress->finish(); + +.. tip:: + + You can also set the current progress by calling the + :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setCurrent` + method. + +The appearance of the progress output can be customized as well, with a number +of different levels of verbosity. Each of these displays different possible +items - like percentage completion, a moving progress bar, or current/total +information (e.g. 10/50):: + + $progress->setFormat(ProgressHelper::FORMAT_QUIET); + $progress->setFormat(ProgressHelper::FORMAT_NORMAL); + $progress->setFormat(ProgressHelper::FORMAT_VERBOSE); + $progress->setFormat(ProgressHelper::FORMAT_QUIET_NOMAX); + // the default value + $progress->setFormat(ProgressHelper::FORMAT_NORMAL_NOMAX); + $progress->setFormat(ProgressHelper::FORMAT_VERBOSE_NOMAX); + +You can also control the different characters and the width used for the +progress bar:: + + // the finished part of the bar + $progress->setBarCharacter('='); + // the unfinished part of the bar + $progress->setEmptyBarCharacter(' '); + $progress->setProgressCharacter('|'); + $progress->setBarWidth(50); + +To see other available options, check the API documentation for +:class:`Symfony\\Component\\Console\\Helper\\ProgressHelper`. + .. caution:: - The Progress Helper was deprecated in Symfony 2.5 and removed in Symfony - 3.0. You should now use the - :doc:`Progress Bar ` instead which - is more powerful. + For performance reasons, be careful if you set the total number of steps + to a high number. For example, if you're iterating over a large number of + items, consider setting the redraw frequency to a higher value by calling + :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setRedrawFrequency`, + so it updates on only some iterations:: + + $progress->start($output, 50000); + + // update every 100 iterations + $progress->setRedrawFrequency(100); + + $i = 0; + while ($i++ < 50000) { + // ... do some work + + $progress->advance(); + } diff --git a/components/console/helpers/questionhelper.rst b/components/console/helpers/questionhelper.rst deleted file mode 100644 index ca799d4c40c..00000000000 --- a/components/console/helpers/questionhelper.rst +++ /dev/null @@ -1,314 +0,0 @@ -.. index:: - single: Console Helpers; Question Helper - -Question Helper -=============== - -The :class:`Symfony\\Component\\Console\\Helper\\QuestionHelper` provides -functions to ask the user for more information. It is included in the default -helper set, which you can get by calling -:method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`:: - - $helper = $this->getHelper('question'); - -The Question Helper has a single method -:method:`Symfony\\Component\\Console\\Command\\Command::ask` that needs an -:class:`Symfony\\Component\\Console\\Input\\InputInterface` instance as the -first argument, an :class:`Symfony\\Component\\Console\\Output\\OutputInterface` -instance as the second argument and a -:class:`Symfony\\Component\\Console\\Question\\Question` as last argument. - -Asking the User for Confirmation --------------------------------- - -Suppose you want to confirm an action before actually executing it. Add -the following to your command:: - - // ... - use Symfony\Component\Console\Input\InputInterface; - use Symfony\Component\Console\Output\OutputInterface; - use Symfony\Component\Console\Question\ConfirmationQuestion; - - class YourCommand extends Command - { - // ... - - public function execute(InputInterface $input, OutputInterface $output) - { - $helper = $this->getHelper('question'); - $question = new ConfirmationQuestion('Continue with this action?', false); - - if (!$helper->ask($input, $output, $question)) { - return; - } - } - } - -In this case, the user will be asked "Continue with this action?". If the user -answers with ``y`` it returns ``true`` or ``false`` if they answer with ``n``. -The second argument to -:method:`Symfony\\Component\\Console\\Question\\ConfirmationQuestion::__construct` -is the default value to return if the user doesn't enter any valid input. If -the second argument is not provided, ``true`` is assumed. - -.. tip:: - - You can customize the regex used to check if the answer means "yes" in the - third argument of the constructor. For instance, to allow anything that - starts with either ``y`` or ``j``, you would set it to:: - - $question = new ConfirmationQuestion( - 'Continue with this action?', - false, - '/^(y|j)/i' - ); - - The regex defaults to ``/^y/i``. - -Asking the User for Information -------------------------------- - -You can also ask a question with more than a simple yes/no answer. For instance, -if you want to know a bundle name, you can add this to your command:: - - use Symfony\Component\Console\Question\Question; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle'); - - $bundle = $helper->ask($input, $output, $question); - } - -The user will be asked "Please enter the name of the bundle". They can type -some name which will be returned by the -:method:`Symfony\\Component\\Console\\Helper\\QuestionHelper::ask` method. -If they leave it empty, the default value (``AcmeDemoBundle`` here) is returned. - -Let the User Choose from a List of Answers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you have a predefined set of answers the user can choose from, you -could use a :class:`Symfony\\Component\\Console\\Question\\ChoiceQuestion` -which makes sure that the user can only enter a valid string -from a predefined list:: - - use Symfony\Component\Console\Question\ChoiceQuestion; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $helper = $this->getHelper('question'); - $question = new ChoiceQuestion( - 'Please select your favorite color (defaults to red)', - array('red', 'blue', 'yellow'), - 0 - ); - $question->setErrorMessage('Color %s is invalid.'); - - $color = $helper->ask($input, $output, $question); - $output->writeln('You have just selected: '.$color); - - // ... do something with the color - } - -The option which should be selected by default is provided with the third -argument of the constructor. The default is ``null``, which means that no -option is the default one. - -If the user enters an invalid string, an error message is shown and the user -is asked to provide the answer another time, until they enter a valid string -or reach the maximum number of attempts. The default value for the maximum number -of attempts is ``null``, which means infinite number of attempts. You can define -your own error message using -:method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setErrorMessage`. - -Multiple Choices -................ - -Sometimes, multiple answers can be given. The ``ChoiceQuestion`` provides this -feature using comma separated values. This is disabled by default, to enable -this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMultiselect`:: - - use Symfony\Component\Console\Question\ChoiceQuestion; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $helper = $this->getHelper('question'); - $question = new ChoiceQuestion( - 'Please select your favorite colors (defaults to red and blue)', - array('red', 'blue', 'yellow'), - '0,1' - ); - $question->setMultiselect(true); - - $colors = $helper->ask($input, $output, $question); - $output->writeln('You have just selected: ' . implode(', ', $colors)); - } - -Now, when the user enters ``1,2``, the result will be: -``You have just selected: blue, yellow``. - -If the user does not enter anything, the result will be: -``You have just selected: red, blue``. - -Autocompletion -~~~~~~~~~~~~~~ - -You can also specify an array of potential answers for a given question. These -will be autocompleted as the user types:: - - use Symfony\Component\Console\Question\Question; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $bundles = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle'); - $question = new Question('Please enter the name of a bundle', 'FooBundle'); - $question->setAutocompleterValues($bundles); - - $name = $helper->ask($input, $output, $question); - } - -Hiding the User's Response -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can also ask a question and hide the response. This is particularly -convenient for passwords:: - - use Symfony\Component\Console\Question\Question; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $question = new Question('What is the database password?'); - $question->setHidden(true); - $question->setHiddenFallback(false); - - $password = $helper->ask($input, $output, $question); - } - -.. caution:: - - When you ask for a hidden response, Symfony will use either a binary, change - stty mode or use another trick to hide the response. If none is available, - it will fallback and allow the response to be visible unless you set this - behavior to ``false`` using - :method:`Symfony\\Component\\Console\\Question\\Question::setHiddenFallback` - like in the example above. In this case, a ``RuntimeException`` - would be thrown. - -Validating the Answer ---------------------- - -You can even validate the answer. For instance, in a previous example you asked -for the bundle name. Following the Symfony naming conventions, it should -be suffixed with ``Bundle``. You can validate that by using the -:method:`Symfony\\Component\\Console\\Question\\Question::setValidator` -method:: - - use Symfony\Component\Console\Question\Question; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle'); - $question->setValidator(function ($answer) { - if ('Bundle' !== substr($answer, -6)) { - throw new \RuntimeException( - 'The name of the bundle should be suffixed with \'Bundle\'' - ); - } - return $answer; - }); - $question->setMaxAttempts(2); - - $name = $helper->ask($input, $output, $question); - } - -The ``$validator`` is a callback which handles the validation. It should -throw an exception if there is something wrong. The exception message is displayed -in the console, so it is a good practice to put some useful information in it. The -callback function should also return the value of the user's input if the validation -was successful. - -You can set the max number of times to ask with the -:method:`Symfony\\Component\\Console\\Question\\Question::setMaxAttempts` method. -If you reach this max number it will use the default value. Using ``null`` means -the amount of attempts is infinite. The user will be asked as long as they provide an -invalid answer and will only be able to proceed if their input is valid. - -Validating a Hidden Response -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can also use a validator with a hidden question:: - - use Symfony\Component\Console\Question\Question; - - // ... - public function execute(InputInterface $input, OutputInterface $output) - { - // ... - $helper = $this->getHelper('question'); - - $question = new Question('Please enter your password'); - $question->setValidator(function ($value) { - if (trim($value) == '') { - throw new \Exception('The password can not be empty'); - } - - return $value; - }); - $question->setHidden(true); - $question->setMaxAttempts(20); - - $password = $helper->ask($input, $output, $question); - } - -Testing a Command that Expects Input ------------------------------------- - -If you want to write a unit test for a command which expects some kind of input -from the command line, you need to set the helper input stream:: - - use Symfony\Component\Console\Helper\QuestionHelper; - use Symfony\Component\Console\Helper\HelperSet; - use Symfony\Component\Console\Tester\CommandTester; - - // ... - public function testExecute() - { - // ... - $commandTester = new CommandTester($command); - - $helper = $command->getHelper('question'); - $helper->setInputStream($this->getInputStream('Test\\n')); - // Equals to a user inputting "Test" and hitting ENTER - // If you need to enter a confirmation, "yes\n" will work - - $commandTester->execute(array('command' => $command->getName())); - - // $this->assertRegExp('/.../', $commandTester->getDisplay()); - } - - protected function getInputStream($input) - { - $stream = fopen('php://memory', 'r+', false); - fputs($stream, $input); - rewind($stream); - - return $stream; - } - -By setting the input stream of the ``QuestionHelper``, you imitate what the -console would do internally with all user input through the CLI. This way -you can test any user interaction (even complex ones) by passing an appropriate -input stream. diff --git a/components/console/helpers/table.rst b/components/console/helpers/table.rst deleted file mode 100644 index 5dc4e827bb3..00000000000 --- a/components/console/helpers/table.rst +++ /dev/null @@ -1,233 +0,0 @@ -.. index:: - single: Console Helpers; Table - -Table -===== - -When building a console application it may be useful to display tabular data: - -.. code-block:: text - - +---------------+--------------------------+------------------+ - | ISBN | Title | Author | - +---------------+--------------------------+------------------+ - | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - | 80-902734-1-6 | And Then There Were None | Agatha Christie | - +---------------+--------------------------+------------------+ - -To display a table, use :class:`Symfony\\Component\\Console\\Helper\\Table`, -set the headers, set the rows and then render the table:: - - use Symfony\Component\Console\Helper\Table; - // ... - - class SomeCommand extends Command - { - public function execute(InputInterface $input, OutputInterface $output) - { - $table = new Table($output); - $table - ->setHeaders(array('ISBN', 'Title', 'Author')) - ->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - )) - ; - $table->render(); - } - } - -You can add a table separator anywhere in the output by passing an instance of -:class:`Symfony\\Component\\Console\\Helper\\TableSeparator` as a row:: - - use Symfony\Component\Console\Helper\TableSeparator; - - $table->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - new TableSeparator(), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - )); - -.. code-block:: text - - +---------------+--------------------------+------------------+ - | ISBN | Title | Author | - +---------------+--------------------------+------------------+ - | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - +---------------+--------------------------+------------------+ - | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - | 80-902734-1-6 | And Then There Were None | Agatha Christie | - +---------------+--------------------------+------------------+ - -The table style can be changed to any built-in styles via -:method:`Symfony\\Component\\Console\\Helper\\Table::setStyle`:: - - // same as calling nothing - $table->setStyle('default'); - - // changes the default style to compact - $table->setStyle('compact'); - $table->render(); - -This code results in: - -.. code-block:: text - - ISBN Title Author - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - -You can also set the style to ``borderless``:: - - $table->setStyle('borderless'); - $table->render(); - -which outputs: - -.. code-block:: text - - =============== ========================== ================== - ISBN Title Author - =============== ========================== ================== - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - =============== ========================== ================== - -If the built-in styles do not fit your need, define your own:: - - use Symfony\Component\Console\Helper\TableStyle; - - // by default, this is based on the default style - $style = new TableStyle(); - - // customize the style - $style - ->setHorizontalBorderChar('|') - ->setVerticalBorderChar('-') - ->setCrossingChar(' ') - ; - - // use the style for this table - $table->setStyle($style); - -Here is a full list of things you can customize: - -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setPaddingChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setHorizontalBorderChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setVerticalBorderChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCrossingChar` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCellHeaderFormat` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setCellRowFormat` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setBorderFormat` -* :method:`Symfony\\Component\\Console\\Helper\\TableStyle::setPadType` - -.. tip:: - - You can also register a style globally:: - - // register the style under the colorful name - Table::setStyleDefinition('colorful', $style); - - // use it for a table - $table->setStyle('colorful'); - - This method can also be used to override a built-in style. - -Spanning Multiple Columns and Rows ----------------------------------- - -To make a table cell that spans multiple columns you can use a :class:`Symfony\\Component\\Console\\Helper\\TableCell`:: - - use Symfony\Component\Console\Helper\Table; - use Symfony\Component\Console\Helper\TableSeparator; - use Symfony\Component\Console\Helper\TableCell; - - $table = new Table($output); - $table - ->setHeaders(array('ISBN', 'Title', 'Author')) - ->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - new TableSeparator(), - array(new TableCell('This value spans 3 columns.', array('colspan' => 3))), - )) - ; - $table->render(); - -This results in: - -.. code-block:: text - - +---------------+---------------+-----------------+ - | ISBN | Title | Author | - +---------------+---------------+-----------------+ - | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - +---------------+---------------+-----------------+ - | This value spans 3 columns. | - +---------------+---------------+-----------------+ - -.. tip:: - - You can create a multiple-line page title using a header cell that spans - the enire table width:: - - $table->setHeaders(array( - array(new TableCell('Main table title', array('colspan' => 3))), - array('ISBN', 'Title', 'Author'), - )) - // ... - - This generates: - - .. code-block:: text - - +-------+-------+--------+ - | Main table title | - +-------+-------+--------+ - | ISBN | Title | Author | - +-------+-------+--------+ - | ... | - +-------+-------+--------+ - -In a similar way you can span multiple rows:: - - use Symfony\Component\Console\Helper\Table; - use Symfony\Component\Console\Helper\TableCell; - - $table = new Table($output); - $table - ->setHeaders(array('ISBN', 'Title', 'Author')) - ->setRows(array( - array( - '978-0521567817', - 'De Monarchia', - new TableCell("Dante Alighieri\nspans multiple rows", array('rowspan' => 2)), - ), - array('978-0804169127', 'Divine Comedy'), - )) - ; - $table->render(); - -This outputs: - -.. code-block:: text - - +----------------+---------------+---------------------+ - | ISBN | Title | Author | - +----------------+---------------+---------------------+ - | 978-0521567817 | De Monarchia | Dante Alighieri | - | 978-0804169127 | Divine Comedy | spans multiple rows | - +----------------+---------------+---------------------+ - -You can use the ``colspan`` and ``rowspan`` options at the same time which allows -you to create any table layout you may wish. diff --git a/components/console/helpers/tablehelper.rst b/components/console/helpers/tablehelper.rst index f0f88a7b57c..537c7674270 100644 --- a/components/console/helpers/tablehelper.rst +++ b/components/console/helpers/tablehelper.rst @@ -4,9 +4,52 @@ Table Helper ============ -.. caution:: +.. versionadded:: 2.3 + The ``table`` helper was introduced in Symfony 2.3. - The Table Helper was deprecated in Symfony 2.5 and removed in - Symfony 3.0. You should now use the - :doc:`Table ` class instead which is - more powerful. +When building a console application it may be useful to display tabular data: + +.. image:: /images/components/console/table.png + +To display a table, use the :class:`Symfony\\Component\\Console\\Helper\\TableHelper`, +set headers, rows and render:: + + $table = $this->getHelper('table'); + $table + ->setHeaders(array('ISBN', 'Title', 'Author')) + ->setRows(array( + array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), + array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), + array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), + array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), + )) + ; + $table->render($output); + +The table layout can be customized as well. There are two ways to customize +table rendering: using named layouts or by customizing rendering options. + +Customize Table Layout using Named Layouts +------------------------------------------ + +The Table helper ships with two preconfigured table layouts: + +* ``TableHelper::LAYOUT_DEFAULT`` + +* ``TableHelper::LAYOUT_BORDERLESS`` + +Layout can be set using :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setLayout` method. + +Customize Table Layout using Rendering Options +---------------------------------------------- + +You can also control table rendering by setting custom rendering option values: + +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPaddingChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setHorizontalBorderChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setVerticalBorderChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCrossingChar` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellHeaderFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setCellRowFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setBorderFormat` +* :method:`Symfony\\Component\\Console\\Helper\\TableHelper::setPadType` diff --git a/components/console/index.rst b/components/console/index.rst index 1ae77d50566..b46548de647 100644 --- a/components/console/index.rst +++ b/components/console/index.rst @@ -6,9 +6,7 @@ Console introduction usage - changing_default_command single_command_tool console_arguments events - logger helpers/index diff --git a/components/console/introduction.rst b/components/console/introduction.rst index 0dfcda479ac..629aaa31cd0 100644 --- a/components/console/introduction.rst +++ b/components/console/introduction.rst @@ -195,11 +195,13 @@ You can also set these colors and options inside the tagname:: // bold text on a yellow background $output->writeln('foo'); -.. _verbosity-levels: - Verbosity Levels ~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + The ``VERBOSITY_VERY_VERBOSE`` and ``VERBOSITY_DEBUG`` constants were introduced + in version 2.3 + The console has five verbosity levels. These are defined in the :class:`Symfony\\Component\\Console\\Output\\OutputInterface`: @@ -225,43 +227,10 @@ level. For example:: $output->writeln(...); } -There are also more semantic methods you can use to test for each of the -verbosity levels:: - - if ($output->isQuiet()) { - // ... - } - - if ($output->isVerbose()) { - // ... - } - - if ($output->isVeryVerbose()) { - // ... - } - - if ($output->isDebug()) { - // ... - } - -.. note:: - - These semantic methods are defined in the ``OutputInterface`` starting from - Symfony 3.0. In previous Symfony versions they are defined in the different - implementations of the interface (e.g. :class:`Symfony\\Component\\Console\\Output\\Output`) - in order to keep backwards compatibility. - When the quiet level is used, all output is suppressed as the default :method:`Symfony\\Component\\Console\\Output\\Output::write` method returns without actually printing. -.. tip:: - - The MonologBridge provides a :class:`Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler` - class that allows you to display messages on the console. This is cleaner - than wrapping your output calls in conditions. For an example use in - the Symfony Framework, see :doc:`/cookbook/logging/monolog_console`. - Using Command Arguments ----------------------- @@ -431,10 +400,10 @@ Console Helpers The console component also contains a set of "helpers" - different small tools capable of helping you with different tasks: -* :doc:`/components/console/helpers/questionhelper`: interactively ask the user for information +* :doc:`/components/console/helpers/dialoghelper`: interactively ask the user for information * :doc:`/components/console/helpers/formatterhelper`: customize the output colorization -* :doc:`/components/console/helpers/progressbar`: shows a progress bar -* :doc:`/components/console/helpers/table`: displays tabular data as a table +* :doc:`/components/console/helpers/progresshelper`: shows a progress bar +* :doc:`/components/console/helpers/tablehelper`: displays tabular data as a table .. _component-console-testing-commands: @@ -572,7 +541,6 @@ Learn More! * :doc:`/components/console/usage` * :doc:`/components/console/single_command_tool` -* :doc:`/components/console/changing_default_command` * :doc:`/components/console/events` * :doc:`/components/console/console_arguments` diff --git a/components/console/logger.rst b/components/console/logger.rst deleted file mode 100644 index 8a713189b05..00000000000 --- a/components/console/logger.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. index:: - single: Console; Logger - -Using the Logger -================ - -The Console component comes with a standalone logger complying with the -`PSR-3`_ standard. Depending on the verbosity setting, log messages will -be sent to the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` -instance passed as a parameter to the constructor. - -The logger does not have any external dependency except ``php-fig/log``. -This is useful for console applications and commands needing a lightweight -PSR-3 compliant logger:: - - namespace Acme; - - use Psr\Log\LoggerInterface; - - class MyDependency - { - private $logger; - - public function __construct(LoggerInterface $logger) - { - $this->logger = $logger; - } - - public function doStuff() - { - $this->logger->info('I love Tony Vairelles\' hairdresser.'); - } - } - -You can rely on the logger to use this dependency inside a command:: - - namespace Acme\Console\Command; - - use Acme\MyDependency; - use Symfony\Component\Console\Command\Command; - use Symfony\Component\Console\Input\InputInterface; - use Symfony\Component\Console\Output\OutputInterface; - use Symfony\Component\Console\Logger\ConsoleLogger; - - class MyCommand extends Command - { - protected function configure() - { - $this - ->setName('my:command') - ->setDescription( - 'Use an external dependency requiring a PSR-3 logger' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $logger = new ConsoleLogger($output); - - $myDependency = new MyDependency($logger); - $myDependency->doStuff(); - } - } - -The dependency will use the instance of -:class:`Symfony\\Component\\Console\\Logger\\ConsoleLogger` as logger. -Log messages emitted will be displayed on the console output. - -Verbosity ---------- - -Depending on the verbosity level that the command is run, messages may or -may not be sent to the :class:`Symfony\\Component\\Console\\Output\\OutputInterface` -instance. - -By default, the console logger behaves like the -:doc:`Monolog's Console Handler `. -The association between the log level and the verbosity can be configured -through the second parameter of the :class:`Symfony\\Component\\Console\\ConsoleLogger` -constructor:: - - use Psr\Log\LogLevel; - // ... - - $verbosityLevelMap = array( - LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL, - LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL, - ); - $logger = new ConsoleLogger($output, $verbosityLevelMap); - -Color ------ - -The logger outputs the log messages formatted with a color reflecting their -level. This behavior is configurable through the third parameter of the -constructor:: - - // ... - $formatLevelMap = array( - LogLevel::CRITICAL => ConsoleLogger::INFO, - LogLevel::DEBUG => ConsoleLogger::ERROR, - ); - $logger = new ConsoleLogger($output, array(), $formatLevelMap); - -.. _PSR-3: http://www.php-fig.org/psr/psr-3/ diff --git a/components/css_selector.rst b/components/css_selector.rst index 588582fb371..3935f3c85ee 100644 --- a/components/css_selector.rst +++ b/components/css_selector.rst @@ -47,12 +47,11 @@ The CssSelector Component ~~~~~~~~~~~~~~~~~~~~~~~~~ The component's only goal is to convert CSS selectors to their XPath -equivalents, using :method:`Symfony\\Component\\CssSelector\\CssSelectorConverter::toXPath`:: +equivalents:: - use Symfony\Component\CssSelector\CssSelectorConverter; + use Symfony\Component\CssSelector\CssSelector; - $converter = new CssSelectorConverter(); - var_dump($converter->toXPath('div.item > h4 > a')); + var_dump(CssSelector::toXPath('div.item > h4 > a')); This gives the following output: diff --git a/components/debug/introduction.rst b/components/debug.rst similarity index 86% rename from components/debug/introduction.rst rename to components/debug.rst index 1042e9e504c..cec6b52f08f 100644 --- a/components/debug/introduction.rst +++ b/components/debug.rst @@ -7,6 +7,10 @@ The Debug Component The Debug component provides tools to ease debugging PHP code. +.. versionadded:: 2.3 + The Debug component was introduced in Symfony 2.3. Previously, the classes + were located in the HttpKernel component. + Installation ------------ @@ -28,8 +32,9 @@ Enabling them all is as easy as it can get:: Debug::enable(); The :method:`Symfony\\Component\\Debug\\Debug::enable` method registers an -error handler, an exception handler and -:doc:`a special class loader `. +error handler and an exception handler. If the :doc:`ClassLoader component +` is available, a special class loader +is also registered. Read the following sections for more information about the different available tools. diff --git a/components/debug/class_loader.rst b/components/debug/class_loader.rst deleted file mode 100644 index ff906101ed1..00000000000 --- a/components/debug/class_loader.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. index:: - single: Class Loader; DebugClassLoader - single: Debug; DebugClassLoader - -Debugging a Class Loader -======================== - -The :class:`Symfony\\Component\\Debug\\DebugClassLoader` attempts to -throw more helpful exceptions when a class isn't found by the registered -autoloaders. All autoloaders that implement a ``findFile()`` method are replaced -with a ``DebugClassLoader`` wrapper. - -Using the ``DebugClassLoader`` is as easy as calling its static -:method:`Symfony\\Component\\Debug\\DebugClassLoader::enable` method:: - - use Symfony\Component\Debug\DebugClassLoader; - - DebugClassLoader::enable(); diff --git a/components/debug/index.rst b/components/debug/index.rst deleted file mode 100644 index 6797789cb1b..00000000000 --- a/components/debug/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -Debug -===== - -.. toctree:: - :maxdepth: 2 - - introduction - class_loader diff --git a/components/dependency_injection/advanced.rst b/components/dependency_injection/advanced.rst index 73b8554c41c..149c3dcff03 100644 --- a/components/dependency_injection/advanced.rst +++ b/components/dependency_injection/advanced.rst @@ -129,227 +129,3 @@ service by asking for the ``bar`` service like this:: foo: class: Example\Foo bar: '@foo' - -Decorating Services -------------------- - -When overriding an existing definition, the old service is lost: - -.. code-block:: php - - $container->register('foo', 'FooService'); - - // this is going to replace the old definition with the new one - // old definition is lost - $container->register('foo', 'CustomFooService'); - -Most of the time, that's exactly what you want to do. But sometimes, -you might want to decorate the old one instead. In this case, the -old service should be kept around to be able to reference it in the -new one. This configuration replaces ``foo`` with a new one, but keeps -a reference of the old one as ``bar.inner``: - -.. configuration-block:: - - .. code-block:: yaml - - bar: - public: false - class: stdClass - decorates: foo - arguments: ["@bar.inner"] - - .. code-block:: xml - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Reference; - - $container->register('bar', 'stdClass') - ->addArgument(new Reference('bar.inner')) - ->setPublic(false) - ->setDecoratedService('foo'); - -Here is what's going on here: the ``setDecoratedService()`` method tells -the container that the ``bar`` service should replace the ``foo`` service, -renaming ``foo`` to ``bar.inner``. -By convention, the old ``foo`` service is going to be renamed ``bar.inner``, -so you can inject it into your new service. - -.. note:: - The generated inner id is based on the id of the decorator service - (``bar`` here), not of the decorated service (``foo`` here). This is - mandatory to allow several decorators on the same service (they need to have - different generated inner ids). - - Most of the time, the decorator should be declared private, as you will not - need to retrieve it as ``bar`` from the container. The visibility of the - decorated ``foo`` service (which is an alias for ``bar``) will still be the - same as the original ``foo`` visibility. - -You can change the inner service name if you want to: - -.. configuration-block:: - - .. code-block:: yaml - - bar: - class: stdClass - public: false - decorates: foo - decoration_inner_name: bar.wooz - arguments: ["@bar.wooz"] - - .. code-block:: xml - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Reference; - - $container->register('bar', 'stdClass') - ->addArgument(new Reference('bar.wooz')) - ->setPublic(false) - ->setDecoratedService('foo', 'bar.wooz'); - -If you want to apply more than one decorator to a service, you can control their -order by configuring the priority of decoration, this can be any integer number -(decorators with higher priorities will be applied first). - -.. configuration-block:: - - .. code-block:: yaml - - foo: - class: Foo - - bar: - class: Bar - public: false - decorates: foo - decoration_priority: 5 - arguments: ['@bar.inner'] - - baz: - class: Baz - public: false - decorates: foo - decoration_priority: 1 - arguments: ['@baz.inner'] - - .. code-block:: xml - - - - - - - - - - - - - - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Reference; - - $container->register('foo', 'Foo') - - $container->register('bar', 'Bar') - ->addArgument(new Reference('bar.inner')) - ->setPublic(false) - ->setDecoratedService('foo', null, 5); - - $container->register('baz', 'Baz') - ->addArgument(new Reference('baz.inner')) - ->setPublic(false) - ->setDecoratedService('foo', null, 1); - -The generated code will be the following: - -.. code-block:: php - - $this->services['foo'] = new Baz(new Bar(new Foo()))); - -Deprecating Services --------------------- - -Once you have decided to deprecate the use of a service (because it is outdated -or you decided not to maintain it anymore), you can deprecate its definition: - -.. configuration-block:: - - .. code-block:: yaml - - acme.my_service: - class: ... - deprecated: The "%service_id%" service is deprecated since 2.8 and will be removed in 3.0. - - .. code-block:: xml - - - - - - - The "%service_id%" service is deprecated since 2.8 and will be removed in 3.0. - - - - - .. code-block:: php - - $container - ->register('acme.my_service', '...') - ->setDeprecated( - true, - 'The "%service_id%" service is deprecated since 2.8 and will be removed in 3.0.' - ) - ; - -Now, every time this service is used, a deprecation warning is triggered, -advising you to stop or to change your uses of that service. - -The message is actually a message template, which replaces occurrences of the -``%service_id%`` placeholder by the service's id. You **must** have at least one -occurrence of the ``%service_id%`` placeholder in your template. - -.. note:: - - The deprecation message is optional. If not set, Symfony will show this default - message: ``The "%service_id%" service is deprecated. You should stop using it, - as it will soon be removed.``. - -.. tip:: - - It is strongly recommended that you define a custom message because the - default one is too generic. A good message informs when this service was - deprecated, until when it will be maintained and the alternative services - to use (if any). - -For service decorators (see above), if the definition does not modify the -deprecated status, it will inherit the status from the definition that is -decorated. - -.. caution:: - - The ability to "un-deprecate" a service is possible only when declaring the - definition in PHP. diff --git a/components/dependency_injection/autowiring.rst b/components/dependency_injection/autowiring.rst deleted file mode 100644 index ad781a2609d..00000000000 --- a/components/dependency_injection/autowiring.rst +++ /dev/null @@ -1,405 +0,0 @@ -.. index:: - single: DependencyInjection; Autowiring - -Defining Services Dependencies Automatically (Autowiring) -========================================================= - -.. versionadded:: 2.8 - Support for autowiring services was introduced in Symfony 2.8. - -Autowiring allows to register services in the container with minimal configuration. -It automatically resolves the service dependencies based on the constructor's -typehint which is useful in the field of `Rapid Application Development`_, -when designing prototypes in early stages of large projects. It makes it easy -to register a service graph and eases refactoring. - -Imagine you're building an API to publish statuses on a Twitter feed, obfuscated -with `ROT13`_ (a special case of the Caesar cipher). - -Start by creating a ROT13 transformer class:: - - // src/AppBundle/Rot13Transformer.php - namespace AppBundle; - - class Rot13Transformer - { - public function transform($value) - { - return str_rot13($value); - } - } - -And now a Twitter client using this transformer:: - - // src/AppBundle/TwitterClient.php - namespace AppBundle; - - class TwitterClient - { - private $transformer; - - public function __construct(Rot13Transformer $transformer) - { - $this->transformer = $transformer; - } - - public function tweet($user, $key, $status) - { - $transformedStatus = $this->transformer->transform($status); - - // ... connect to Twitter and send the encoded status - } - } - -The DependencyInjection component will be able to automatically register -the dependencies of this ``TwitterClient`` class when the ``twitter_client`` -service is marked as autowired: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - twitter_client: - class: 'AppBundle\TwitterClient' - autowire: true - - .. code-block:: xml - - - - - - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Definition; - - // ... - $definition = new Definition('AppBundle\TwitterClient'); - $definition->setAutowired(true); - - $container->setDefinition('twitter_client', $definition); - -The autowiring subsystem will detect the dependencies of the ``TwitterClient`` -class by parsing its constructor. For instance it will find here an instance of -a ``Rot13Transformer`` as dependency. If an existing service definition (and only -one – see below) is of the required type, this service will be injected. If it's -not the case (like in this example), the subsystem is smart enough to automatically -register a private service for the ``Rot13Transformer`` class and set it as first -argument of the ``twitter_client`` service. Again, it can work only if there is one -class of the given type. If there are several classes of the same type, you must -use an explicit service definition or register a default implementation. - -As you can see, the autowiring feature drastically reduces the amount of configuration -required to define a service. No more arguments section! It also makes it easy -to change the dependencies of the ``TwitterClient`` class: just add or remove typehinted -arguments in the constructor and you are done. There is no need anymore to search -and edit related service definitions. - -Here is a typical controller using the ``twitter_client`` service:: - - // src/AppBundle/Controller/DefaultController.php - namespace AppBundle\Controller; - - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; - use Symfony\Bundle\FrameworkBundle\Controller\Controller; - use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; - - class DefaultController extends Controller - { - /** - * @Route("/tweet") - * @Method("POST") - */ - public function tweetAction(Request $request) - { - $user = $request->request->get('user'); - $key = $request->request->get('key'); - $status = $request->request->get('status'); - - if (!$user || !$key || !$status) { - throw new BadRequestHttpException(); - } - - $this->get('twitter_client')->tweet($user, $key, $status); - - return new Response('OK'); - } - } - -You can give the API a try using ``curl``: - -.. code-block:: bash - - $ curl -d "user=kevin&key=ABCD&status=Hello" http://localhost:8000/tweet - -It should return ``OK``. - -Working with Interfaces ------------------------ - -You might also find yourself using abstractions instead of implementations (especially -in grown applications) as it allows to easily replace some dependencies without -modifying the class depending of them. - -To follow this best practice, constructor arguments must be typehinted with interfaces -and not concrete classes. It allows to replace easily the current implementation -if necessary. It also allows to use other transformers. - -Let's introduce a ``TransformerInterface``:: - - // src/AppBundle/TransformerInterface.php - namespace AppBundle; - - interface TransformerInterface - { - public function transform($value); - } - -Then edit ``Rot13Transformer`` to make it implementing the new interface:: - - // ... - - class Rot13Transformer implements TransformerInterface - - // ... - - -And update ``TwitterClient`` to depend of this new interface:: - - class TwitterClient - { - // ... - - public function __construct(TransformerInterface $transformer) - { - // ... - } - - // ... - } - -Finally the service definition must be updated because, obviously, the autowiring -subsystem isn't able to find itself the interface implementation to register: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - rot13_transformer: - class: 'AppBundle\Rot13Transformer' - - twitter_client: - class: 'AppBundle\TwitterClient' - autowire: true - - .. code-block:: xml - - - - - - - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Definition; - - // ... - $definition1 = new Definition('AppBundle\Rot13Transformer'); - $container->setDefinition('rot13_transformer', $definition1); - - $definition2 = new Definition('AppBundle\TwitterClient'); - $definition2->setAutowired(true); - $container->setDefinition('twitter_client', $definition2); - -The autowiring subsystem detects that the ``rot13_transformer`` service implements -the ``TransformerInterface`` and injects it automatically. Even when using -interfaces (and you should), building the service graph and refactoring the project -is easier than with standard definitions. - -Dealing with Multiple Implementations of the Same Type ------------------------------------------------------- - -Last but not least, the autowiring feature allows to specify the default implementation -of a given type. Let's introduce a new implementation of the ``TransformerInterface`` -returning the result of the ROT13 transformation uppercased:: - - // src/AppBundle/UppercaseRot13Transformer.php - namespace AppBundle; - - class UppercaseTransformer implements TransformerInterface - { - private $transformer; - - public function __construct(TransformerInterface $transformer) - { - $this->transformer = $transformer; - } - - public function transform($value) - { - return strtoupper($this->transformer->transform($value)); - } - } - -This class is intended to decorate the any transformer and return its value uppercased. - -We can now refactor the controller to add another endpoint leveraging this new -transformer:: - - // src/AppBundle/Controller/DefaultController.php - namespace AppBundle\Controller; - - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; - use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; - use Symfony\Bundle\FrameworkBundle\Controller\Controller; - use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; - - class DefaultController extends Controller - { - /** - * @Route("/tweet") - * @Method("POST") - */ - public function tweetAction(Request $request) - { - return $this->tweet($request, 'twitter_client'); - } - - /** - * @Route("/tweet-uppercase") - * @Method("POST") - */ - public function tweetUppercaseAction(Request $request) - { - return $this->tweet($request, 'uppercase_twitter_client'); - } - - private function tweet(Request $request, $service) - { - $user = $request->request->get('user'); - $key = $request->request->get('key'); - $status = $request->request->get('status'); - - if (!$user || !$key || !$status) { - throw new BadRequestHttpException(); - } - - $this->get($service)->tweet($user, $key, $status); - - return new Response('OK'); - } - } - -The last step is to update service definitions to register this new implementation -and a Twitter client using it: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - rot13_transformer: - class: AppBundle\Rot13Transformer - autowiring_types: AppBundle\TransformerInterface - - twitter_client: - class: AppBundle\TwitterClient - autowire: true - - uppercase_rot13_transformer: - class: AppBundle\UppercaseRot13Transformer - autowire: true - - uppercase_twitter_client: - class: AppBundle\TwitterClient - arguments: ['@uppercase_rot13_transformer'] - - .. code-block:: xml - - - - - - - - AppBundle\TransformerInterface - - - - - - - - - - .. code-block:: php - - use Symfony\Component\DependencyInjection\Reference; - use Symfony\Component\DependencyInjection\Definition; - - // ... - $definition1 = new Definition('AppBundle\Rot13Transformer'); - $definition1->setAutowiringTypes(array('AppBundle\TransformerInterface')); - $container->setDefinition('rot13_transformer', $definition1); - - $definition2 = new Definition('AppBundle\TwitterClient'); - $definition2->setAutowired(true); - $container->setDefinition('twitter_client', $definition2); - - $definition3 = new Definition('AppBundle\UppercaseRot13Transformer'); - $definition3->setAutowired(true); - $container->setDefinition('uppercase_rot13_transformer', $definition3); - - $definition4 = new Definition('AppBundle\TwitterClient'); - $definition4->addArgument(new Reference('uppercase_rot13_transformer')); - $container->setDefinition('uppercase_twitter_client', $definition4); - -This deserves some explanations. You now have two services implementing the -``TransformerInterface``. The autowiring subsystem cannot guess which one -to use which leads to errors like this: - -.. code-block:: text - - [Symfony\Component\DependencyInjection\Exception\RuntimeException] - Unable to autowire argument of type "AppBundle\TransformerInterface" for the service "twitter_client". - -Fortunately, the ``autowiring_types`` key is here to specify which implementation -to use by default. This key can take a list of types if necessary. - -Thanks to this setting, the ``rot13_transformer`` service is automatically injected -as an argument of the ``uppercase_rot13_transformer`` and ``twitter_client`` services. For -the ``uppercase_twitter_client``, we use a standard service definition to inject -the specific ``uppercase_rot13_transformer`` service. - -As for other RAD features such as the FrameworkBundle controller or annotations, -keep in mind to not use autowiring in public bundles nor in large projects with -complex maintenance needs. - -.. _Rapid Application Development: https://en.wikipedia.org/wiki/Rapid_application_development -.. _ROT13: https://en.wikipedia.org/wiki/ROT13 diff --git a/components/dependency_injection/compilation.rst b/components/dependency_injection/compilation.rst index d821857a475..388815f3b6c 100644 --- a/components/dependency_injection/compilation.rst +++ b/components/dependency_injection/compilation.rst @@ -281,6 +281,10 @@ file but also load a secondary one only if a certain parameter is set:: Prepending Configuration Passed to the Extension ------------------------------------------------ +.. versionadded:: 2.2 + The ability to prepend the configuration of a bundle was introduced + in Symfony 2.2. + An Extension can prepend the configuration of any Bundle before the ``load()`` method is called by implementing :class:`Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface`:: @@ -306,89 +310,46 @@ For more details, see :doc:`/cookbook/bundles/prepend_extension`, which is specific to the Symfony Framework, but contains more details about this feature. -.. _creating-a-compiler-pass: -.. _components-di-compiler-pass: - -Execute Code During Compilation -------------------------------- +Creating a Compiler Pass +------------------------ -You can also execute custom code during compilation by writing your own -compiler pass. By implementing +You can also create and register your own compiler passes with the container. +To create a compiler pass it needs to implement the :class:`Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface` -in your extension, the added ``process()`` method will be called during -compilation:: +interface. The compiler pass gives you an opportunity to manipulate the +service definitions that have been compiled. This can be very powerful, +but is not something needed in everyday use. + +The compiler pass must have the ``process`` method which is passed the container +being compiled:: - // ... use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + use Symfony\Component\DependencyInjection\ContainerBuilder; - class AcmeDemoExtension implements ExtensionInterface, CompilerPassInterface + class CustomCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { - // ... do something during the compilation + // ... } - - // ... } -As ``process()`` is called *after* all extensions are loaded, it allows you to -edit service definitions of other extensions as well as retrieving information -about service definitions. - The container's parameters and definitions can be manipulated using the -methods described in :doc:`/components/dependency_injection/definitions`. - -.. note:: - - Please note that the ``process()`` method in the extension class is - called during the optimization step. You can read - :ref:`the next section ` if you - need to edit the container during another step. - -.. note:: - - As a rule, only work with services definition in a compiler pass and do not - create service instances. In practice, this means using the methods - ``has()``, ``findDefinition()``, ``getDefinition()``, ``setDefinition()``, - etc. instead of ``get()``, ``set()``, etc. - -.. tip:: - - Make sure your compiler pass does not require services to exist. Abort the - method call if some required service is not available. +methods described in the :doc:`/components/dependency_injection/definitions`. +One common thing to do in a compiler pass is to search for all services +that have a certain tag in order to process them in some way or dynamically +plug each into some other service. -A common use-case of compiler passes is to search for all service definitions -that have a certain tag in order to process dynamically plug each into some -other service. See the section on :ref:`service tags ` -for an example. +Registering a Compiler Pass +--------------------------- -.. _components-di-separate-compiler-passes: - -Creating Separate Compiler Passes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes, you need to do more than one thing during compliation, want to use -compiler passes without an extension or you need to execute some code at -another step in the compilation process. In these cases, you can create a new -class implementing the ``CompilerPassInterface``:: - - use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; - use Symfony\Component\DependencyInjection\ContainerBuilder; - - class CustomPass implements CompilerPassInterface - { - public function process(ContainerBuilder $container) - { - // ... do something during the compilation - } - } - -You then need to register your custom pass with the container:: +You need to register your custom pass with the container. Its process method +will then be called when the container is compiled:: use Symfony\Component\DependencyInjection\ContainerBuilder; $container = new ContainerBuilder(); - $container->addCompilerPass(new CustomPass()); + $container->addCompilerPass(new CustomCompilerPass); .. note:: @@ -397,16 +358,17 @@ You then need to register your custom pass with the container:: more details. Controlling the Pass Ordering -............................. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The default compiler passes are grouped into optimization passes and removal passes. The optimization passes run first and include tasks such as resolving references within the definitions. The removal passes perform tasks such -as removing private aliases and unused services. When registering compiler -passes using ``addCompilerPass()``, you can configure when your compiler pass -is run. By default, they are run before the optimization passes. +as removing private aliases and unused services. You can choose where in +the order any custom passes you add are run. By default they will be run +before the optimization passes. -You can use the following constants to determine when your pass is executed: +You can use the following constants as the second argument when registering +a pass with the container to control where it goes in the order: * ``PassConfig::TYPE_BEFORE_OPTIMIZATION`` * ``PassConfig::TYPE_OPTIMIZE`` @@ -415,11 +377,14 @@ You can use the following constants to determine when your pass is executed: * ``PassConfig::TYPE_AFTER_REMOVING`` For example, to run your custom pass after the default removal passes have -been run, use:: +been run:: - // ... + use Symfony\Component\DependencyInjection\ContainerBuilder; + use Symfony\Component\DependencyInjection\Compiler\PassConfig; + + $container = new ContainerBuilder(); $container->addCompilerPass( - new CustomPass(), + new CustomCompilerPass, PassConfig::TYPE_AFTER_REMOVING ); diff --git a/components/dependency_injection/factories.rst b/components/dependency_injection/factories.rst index e97fc0f4aa6..7d8358d2c29 100644 --- a/components/dependency_injection/factories.rst +++ b/components/dependency_injection/factories.rst @@ -28,8 +28,8 @@ object:: } To make the ``NewsletterManager`` object available as a service, you can -configure the service container to use the -``NewsletterManagerFactory::createNewsletterManager()`` factory method: +configure the service container to use the ``NewsletterManagerFactory`` +factory class: .. configuration-block:: @@ -37,8 +37,9 @@ configure the service container to use the services: newsletter_manager: - class: NewsletterManager - factory: [NewsletterManagerFactory, createNewsletterManager] + class: NewsletterManager + factory_class: NewsletterManagerFactory + factory_method: createNewsletterManager .. code-block:: xml @@ -48,9 +49,11 @@ configure the service container to use the xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - - + @@ -60,7 +63,8 @@ configure the service container to use the // ... $definition = new Definition('NewsletterManager'); - $definition->setFactory(array('NewsletterManagerFactory', 'createNewsletterManager')); + $definition->setFactoryClass('NewsletterManagerFactory'); + $definition->setFactoryMethod('createNewsletterManager'); $container->setDefinition('newsletter_manager', $definition); @@ -72,21 +76,23 @@ configure the service container to use the the configured class name may be used by compiler passes and therefore should be set to a sensible value. -Now, the method will be called statically. If the factory class itself should -be instantiated and the resulting object's method called, configure the factory -itself as a service. In this case, the method (e.g. get) should be changed to -be non-static. +When you specify the class to use for the factory (via ``factory_class``) +the method will be called statically. If the factory itself should be instantiated +and the resulting object's method called, configure the factory itself +as a service. In this case, the method (e.g. ``createNewsletterManager``) +should be changed to be non-static: .. configuration-block:: .. code-block:: yaml services: - newsletter_manager.factory: - class: NewsletterManagerFactory + newsletter_manager_factory: + class: NewsletterManagerFactory newsletter_manager: - class: NewsletterManager - factory: ["@newsletter_manager.factory", createNewsletterManager] + class: NewsletterManager + factory_service: newsletter_manager_factory + factory_method: createNewsletterManager .. code-block:: xml @@ -96,28 +102,36 @@ be non-static. xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + - - - + .. code-block:: php - use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; - // ... - $container->register('newsletter_manager.factory', 'NewsletterManagerFactory'); - - $newsletterManager = new Definition(); - $newsletterManager->setFactory(array( - new Reference('newsletter_manager.factory'), - 'createNewsletterManager' + $container->setDefinition('newsletter_manager_factory', new Definition( + 'NewsletterManager' )); - $container->setDefinition('newsletter_manager', $newsletterManager); + $container->setDefinition('newsletter_manager', new Definition( + 'NewsletterManagerFactory' + ))->setFactoryService( + 'newsletter_manager_factory' + )->setFactoryMethod( + 'createNewsletterManager' + ); + +.. note:: + + The factory service is specified by its id name and not a reference + to the service itself. So, you do not need to use the ``@`` syntax for + this in YAML configurations. Passing Arguments to the Factory Method --------------------------------------- @@ -131,12 +145,12 @@ method in the previous example takes the ``templating`` service as an argument: .. code-block:: yaml services: - newsletter_manager.factory: - class: NewsletterManagerFactory - + newsletter_manager_factory: + class: NewsletterManagerFactory newsletter_manager: - class: NewsletterManager - factory: ["@newsletter_manager.factory", createNewsletterManager] + class: NewsletterManager + factory_service: newsletter_manager_factory + factory_method: createNewsletterManager arguments: - '@templating' @@ -148,29 +162,32 @@ method in the previous example takes the ``templating`` service as an argument: xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + - - - + + + .. code-block:: php - use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; // ... - $container->register('newsletter_manager.factory', 'NewsletterManagerFactory'); - - $newsletterManager = new Definition( + $container->setDefinition('newsletter_manager_factory', new Definition( + 'NewsletterManagerFactory' + )); + $container->setDefinition('newsletter_manager', new Definition( 'NewsletterManager', array(new Reference('templating')) - ); - $newsletterManager->setFactory(array( - new Reference('newsletter_manager.factory'), + ))->setFactoryService( + 'newsletter_manager_factory' + )->setFactoryMethod( 'createNewsletterManager' - )); - $container->setDefinition('newsletter_manager', $newsletterManager); + ); diff --git a/components/dependency_injection/index.rst b/components/dependency_injection/index.rst index bc6ec0daf73..313f29af3f4 100644 --- a/components/dependency_injection/index.rst +++ b/components/dependency_injection/index.rst @@ -8,7 +8,6 @@ DependencyInjection types parameters definitions - autowiring synthetic_services compilation tags diff --git a/components/dependency_injection/lazy_services.rst b/components/dependency_injection/lazy_services.rst index 21c78075888..38f0968631f 100644 --- a/components/dependency_injection/lazy_services.rst +++ b/components/dependency_injection/lazy_services.rst @@ -4,6 +4,9 @@ Lazy Services ============= +.. versionadded:: 2.3 + Lazy services were introduced in Symfony 2.3. + Why Lazy Services? ------------------ @@ -27,7 +30,7 @@ the `ProxyManager bridge`_: .. code-block:: bash - $ composer require symfony/proxy-manager-bridge + $ composer require symfony/proxy-manager-bridge:~2.3 .. note:: diff --git a/components/dependency_injection/parentservices.rst b/components/dependency_injection/parentservices.rst index b153db59f8b..aa1ec8622d8 100644 --- a/components/dependency_injection/parentservices.rst +++ b/components/dependency_injection/parentservices.rst @@ -277,7 +277,8 @@ called when the child services are instantiated. .. caution:: - The ``abstract`` and ``tags`` attributes are always taken from the child service. + The ``scope``, ``abstract`` and ``tags`` attributes are always taken + from the child service. The parent service is abstract as it should not be directly retrieved from the container or passed into another service. It exists merely as a "template" diff --git a/components/dependency_injection/tags.rst b/components/dependency_injection/tags.rst index 2cb5713401a..c92cebaf3f8 100644 --- a/components/dependency_injection/tags.rst +++ b/components/dependency_injection/tags.rst @@ -117,14 +117,11 @@ Notice that each was given a tag named ``acme_mailer.transport``. This is the custom tag that you'll use in your compiler pass. The compiler pass is what makes this tag "mean" something. -.. _components-di-compiler-pass-tags: -.. _create-a-compilerpass: +Create a ``CompilerPass`` +------------------------- -Create a Compiler Pass ----------------------- - -You can now use a :ref:`compiler pass ` to ask the -container for any services with the ``acme_mailer.transport`` tag:: +Your compiler pass can now ask the container for any services with the +custom tag:: use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -157,7 +154,7 @@ container for any services with the ``acme_mailer.transport`` tag:: The ``process()`` method checks for the existence of the ``acme_mailer.transport_chain`` service, then looks for all services tagged ``acme_mailer.transport``. It adds to the definition of the ``acme_mailer.transport_chain`` service a -call to ``addTransport()`` for each ``acme_mailer.transport`` service it has +call to ``addTransport()`` for each "acme_mailer.transport" service it has found. The first argument of each of these calls will be the mailer transport service itself. @@ -178,13 +175,6 @@ run when the container is compiled:: framework. See :doc:`/cookbook/service_container/compiler_passes` for more details. -.. tip:: - - When implementing the ``CompilerPassInterface`` in a service extension, you - do not need to register it. See the - :ref:`components documentation ` for more - information. - Adding Additional Attributes on Tags ------------------------------------ @@ -306,3 +296,4 @@ The double loop may be confusing. This is because a service can have more than one tag. You tag a service twice or more with the ``acme_mailer.transport`` tag. The second foreach loop iterates over the ``acme_mailer.transport`` tags set for the current service and gives you the attributes. + diff --git a/components/dom_crawler.rst b/components/dom_crawler.rst index d4cc5d79d7f..63efa9f8223 100644 --- a/components/dom_crawler.rst +++ b/components/dom_crawler.rst @@ -98,64 +98,6 @@ To remove a node the anonymous function must return false. All filter methods return a new :class:`Symfony\\Component\\DomCrawler\\Crawler` instance with filtered content. -Both the :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath` and -:method:`Symfony\\Component\\DomCrawler\\Crawler::filter` methods work with -XML namespaces, which can be either automatically discovered or registered -explicitly. - -Consider the XML below: - -.. code-block:: xml - - - - tag:youtube.com,2008:video:kgZRZmEc9j4 - - - - Chordates - CrashCourse Biology #24 - widescreen - - - -This can be filtered with the ``Crawler`` without needing to register namespace -aliases both with :method:`Symfony\\Component\\DomCrawler\\Crawler::filterXPath`:: - - $crawler = $crawler->filterXPath('//default:entry/media:group//yt:aspectRatio'); - -and :method:`Symfony\\Component\\DomCrawler\\Crawler::filter`:: - - use Symfony\Component\CssSelector\CssSelector; - - CssSelector::disableHtmlExtension(); - $crawler = $crawler->filter('default|entry media|group yt|aspectRatio'); - -.. note:: - - The default namespace is registered with a prefix "default". It can be - changed with the - :method:`Symfony\\Component\\DomCrawler\\Crawler::setDefaultNamespacePrefix` - method. - - The default namespace is removed when loading the content if it's the only - namespace in the document. It's done to simplify the xpath queries. - -Namespaces can be explicitly registered with the -:method:`Symfony\\Component\\DomCrawler\\Crawler::registerNamespace` method:: - - $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); - $crawler = $crawler->filterXPath('//m:group//yt:aspectRatio'); - -.. caution:: - - To query XML with a CSS selector, the HTML extension needs to be disabled with - :method:`CssSelector::disableHtmlExtension ` - to avoid converting the selector to lowercase. - Node Traversing ~~~~~~~~~~~~~~~ @@ -190,11 +132,6 @@ Get all the child or parent nodes:: Accessing Node Values ~~~~~~~~~~~~~~~~~~~~~ -Access the node name (HTML tag name) of the first node of the current selection (eg. "p" or "div"):: - - // will return the node name (HTML tag name) of the first child element under - $tag = $crawler->filterXPath('//body/*')->nodeName(); - Access the value of the first node of the current selection:: $message = $crawler->filterXPath('//body/p')->text(); @@ -223,6 +160,11 @@ Call an anonymous function on each node of the list:: return $node->text(); }); +.. versionadded:: 2.3 + As seen here, in Symfony 2.3, the ``each`` and ``reduce`` Closure functions + are passed a ``Crawler`` as the first argument. Previously, that argument + was a :phpclass:`DOMNode`. + The anonymous function receives the node (as a Crawler) and the position as arguments. The result is an array of values returned by the anonymous function calls. @@ -289,6 +231,14 @@ and :phpclass:`DOMNode` objects: $html = $crawler->html(); + The ``html`` method is new in Symfony 2.3. + + .. caution:: + + Due to an issue in PHP, the ``html()`` method returns wrongly decoded HTML + entities in PHP versions lower than 5.3.6 (for example, it returns ``•`` + instead of ``•``). + Links ~~~~~ @@ -399,9 +349,6 @@ and uploading files:: // even fake a file upload $form['registration[photo]']->upload('/path/to/lucas.jpg'); -Using the Form Data -................... - What's the point of doing all of this? If you're testing internally, you can grab the information off of your form as if it had just been submitted by using the PHP values:: @@ -437,22 +384,5 @@ directly:: // submit that form $crawler = $client->submit($form); -.. _components-dom-crawler-invalid: - -Selecting Invalid Choice Values -............................... - -By default, choice fields (select, radio) have internal validation activated -to prevent you from setting invalid values. If you want to be able to set -invalid values, you can use the ``disableValidation()`` method on either -the whole form or specific field(s):: - - // Disable validation for a specific field - $form['country']->disableValidation()->select('Invalid value'); - - // Disable validation for the whole form - $form->disableValidation(); - $form['country']->select('Invalid value'); - .. _`Goutte`: https://github.com/FriendsOfPHP/Goutte .. _Packagist: https://packagist.org/packages/symfony/dom-crawler diff --git a/components/event_dispatcher/immutable_dispatcher.rst b/components/event_dispatcher/immutable_dispatcher.rst index da757aeacce..7df2aecf282 100644 --- a/components/event_dispatcher/immutable_dispatcher.rst +++ b/components/event_dispatcher/immutable_dispatcher.rst @@ -4,6 +4,9 @@ The Immutable Event Dispatcher ============================== +.. versionadded:: 2.1 + This feature was introduced in Symfony 2.1. + The :class:`Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher` is a locked or frozen event dispatcher. The dispatcher cannot register new listeners or subscribers. diff --git a/components/event_dispatcher/introduction.rst b/components/event_dispatcher/introduction.rst index 823cd54a8ed..9311ad9dc75 100644 --- a/components/event_dispatcher/introduction.rst +++ b/components/event_dispatcher/introduction.rst @@ -194,14 +194,14 @@ determine which instance is passed. and the :doc:`DependencyInjection component `, you can use the - :class:`Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass` - to tag services as event listeners:: + :class:`Symfony\\Component\\HttpKernel\\DependencyInjection\\RegisterListenersPass` + from the HttpKernel component to tag services as event listeners:: use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; - use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; + use Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass; $containerBuilder = new ContainerBuilder(new ParameterBag()); $containerBuilder->addCompilerPass(new RegisterListenersPass()); @@ -439,11 +439,11 @@ method which returns a boolean value:: EventDispatcher Aware Events and Listeners ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The ``EventDispatcher`` always passes the dispatched event, the event's -name and a reference to itself to the listeners. This can be used in some -advanced usages of the ``EventDispatcher`` like dispatching other events -in listeners, event chaining or even lazy loading of more listeners into -the dispatcher object as shown in the following examples. +The ``EventDispatcher`` always injects a reference to itself in the passed +event object. This means that all listeners have direct access to the +``EventDispatcher`` object that notified the listener via the passed ``Event`` +object's :method:`Symfony\\Component\\EventDispatcher\\Event::getDispatcher` +method. This can lead to some advanced applications of the ``EventDispatcher`` including dispatching other events inside listeners, chaining events or even @@ -487,15 +487,20 @@ and so on. Event Name Introspection ~~~~~~~~~~~~~~~~~~~~~~~~ -The ``EventDispatcher`` instance, as well as the name of the event that -is dispatched, are passed as arguments to the listener:: +Since the ``EventDispatcher`` already knows the name of the event when dispatching +it, the event name is also injected into the +:class:`Symfony\\Component\\EventDispatcher\\Event` objects, making it available +to event listeners via the :method:`Symfony\\Component\\EventDispatcher\\Event::getName` +method. + +The event name, (as with any other data in a custom event object) can be +used as part of the listener's processing logic:: use Symfony\Component\EventDispatcher\Event; - use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Foo { - public function myEventListener(Event $event, $eventName, EventDispatcherInterface $dispatcher) + public function myEventListener(Event $event) { // ... do something with the event name } diff --git a/components/event_dispatcher/traceable_dispatcher.rst b/components/event_dispatcher/traceable_dispatcher.rst index f76b70ae938..70fad87bb03 100644 --- a/components/event_dispatcher/traceable_dispatcher.rst +++ b/components/event_dispatcher/traceable_dispatcher.rst @@ -5,13 +5,13 @@ The Traceable Event Dispatcher ============================== -The :class:`Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher` +The :class:`Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher` is an event dispatcher that wraps any other event dispatcher and can then be used to determine which event listeners have been called by the dispatcher. Pass the event dispatcher to be wrapped and an instance of the :class:`Symfony\\Component\\Stopwatch\\Stopwatch` to its constructor:: - use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; + use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; use Symfony\Component\Stopwatch\Stopwatch; // the event dispatcher to debug diff --git a/components/expression_language/caching.rst b/components/expression_language/caching.rst deleted file mode 100644 index b06176a0375..00000000000 --- a/components/expression_language/caching.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. index:: - single: Caching; ExpressionLanguage - -Caching Expressions Using Parser Caches -======================================= - -The ExpressionLanguage component already provides a -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::compile` -method to be able to cache the expressions in plain PHP. But internally, the -component also caches the parsed expressions, so duplicated expressions can be -compiled/evaluated quicker. - -The Workflow ------------- - -Both :method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::evaluate` -and ``compile()`` need to do some things before each can provide the return -values. For ``evaluate()``, this overhead is even bigger. - -Both methods need to tokenize and parse the expression. This is done by the -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::parse` -method. It returns a :class:`Symfony\\Component\\ExpressionLanguage\\ParsedExpression`. -Now, the ``compile()`` method just returns the string conversion of this object. -The ``evaluate()`` method needs to loop through the "nodes" (pieces of an -expression saved in the ``ParsedExpression``) and evaluate them on the fly. - -To save time, the ``ExpressionLanguage`` caches the ``ParsedExpression`` so -it can skip the tokenize and parse steps with duplicate expressions. -The caching is done by a -:class:`Symfony\\Component\\ExpressionLanguage\\ParserCache\\ParserCacheInterface` -instance (by default, it uses an -:class:`Symfony\\Component\\ExpressionLanguage\\ParserCache\\ArrayParserCache`). -You can customize this by creating a custom ``ParserCache`` and injecting this -in the object using the constructor:: - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - use Acme\ExpressionLanguage\ParserCache\MyDatabaseParserCache; - - $cache = new MyDatabaseParserCache(...); - $language = new ExpressionLanguage($cache); - -.. note:: - - The `DoctrineBridge`_ provides a Parser Cache implementation using the - `doctrine cache library`_, which gives you caching for all sorts of cache - strategies, like Apc, Filesystem and Memcached. - -Using Parsed and Serialized Expressions ---------------------------------------- - -Both ``evaluate()`` and ``compile()`` can handle ``ParsedExpression`` and -``SerializedParsedExpression``:: - - // ... - - // the parse() method returns a ParsedExpression - $expression = $language->parse('1 + 4', array()); - - var_dump($language->evaluate($expression)); // prints 5 - -.. code-block:: php - - use Symfony\Component\ExpressionLanguage\SerializedParsedExpression; - // ... - - $expression = new SerializedParsedExpression( - '1 + 4', - serialize($language->parse('1 + 4', array())->getNodes()) - ); - - var_dump($language->evaluate($expression)); // prints 5 - -.. _DoctrineBridge: https://github.com/symfony/doctrine-bridge -.. _`doctrine cache library`: http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/caching.html diff --git a/components/expression_language/extending.rst b/components/expression_language/extending.rst deleted file mode 100644 index eeb9963c6c6..00000000000 --- a/components/expression_language/extending.rst +++ /dev/null @@ -1,126 +0,0 @@ -.. index:: - single: Extending; ExpressionLanguage - -Extending the ExpressionLanguage -================================ - -The ExpressionLanguage can be extended by adding custom functions. For -instance, in the Symfony Framework, the security has custom functions to check -the user's role. - -.. note:: - - If you want to learn how to use functions in an expression, read - ":ref:`component-expression-functions`". - -Registering Functions ---------------------- - -Functions are registered on each specific ``ExpressionLanguage`` instance. -That means the functions can be used in any expression executed by that -instance. - -To register a function, use -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::register`. -This method has 3 arguments: - -* **name** - The name of the function in an expression; -* **compiler** - A function executed when compiling an expression using the - function; -* **evaluator** - A function executed when the expression is evaluated. - -.. code-block:: php - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - - $language = new ExpressionLanguage(); - $language->register('lowercase', function ($str) { - return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str); - }, function ($arguments, $str) { - if (!is_string($str)) { - return $str; - } - - return strtolower($str); - }); - - var_dump($language->evaluate('lowercase("HELLO")')); - -This will print ``hello``. Both the **compiler** and **evaluator** are passed -an ``arguments`` variable as their first argument, which is equal to the -second argument to ``evaluate()`` or ``compile()`` (e.g. the "values" when -evaluating or the "names" if compiling). - -.. _components-expression-language-provider: - -Using Expression Providers --------------------------- - -When you use the ``ExpressionLanguage`` class in your library, you often want -to add custom functions. To do so, you can create a new expression provider by -creating a class that implements -:class:`Symfony\\Component\\ExpressionLanguage\\ExpressionFunctionProviderInterface`. - -This interface requires one method: -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionFunctionProviderInterface::getFunctions`, -which returns an array of expression functions (instances of -:class:`Symfony\\Component\\ExpressionLanguage\\ExpressionFunction`) to -register. - -.. code-block:: php - - use Symfony\Component\ExpressionLanguage\ExpressionFunction; - use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; - - class StringExpressionLanguageProvider implements ExpressionFunctionProviderInterface - { - public function getFunctions() - { - return array( - new ExpressionFunction('lowercase', function ($str) { - return sprintf('(is_string(%1$s) ? strtolower(%1$s) : %1$s)', $str); - }, function ($arguments, $str) { - if (!is_string($str)) { - return $str; - } - - return strtolower($str); - }), - ); - } - } - -You can register providers using -:method:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage::registerProvider` -or by using the second argument of the constructor:: - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - - // using the constructor - $language = new ExpressionLanguage(null, array( - new StringExpressionLanguageProvider(), - // ... - )); - - // using registerProvider() - $language->registerProvider(new StringExpressionLanguageProvider()); - -.. tip:: - - It is recommended to create your own ``ExpressionLanguage`` class in your - library. Now you can add the extension by overriding the constructor:: - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; - use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; - - class ExpressionLanguage extends BaseExpressionLanguage - { - public function __construct(ParserCacheInterface $parser = null, array $providers = array()) - { - // prepend the default provider to let users override it easily - array_unshift($providers, new StringExpressionLanguageProvider()); - - parent::__construct($parser, $providers); - } - } - diff --git a/components/expression_language/index.rst b/components/expression_language/index.rst deleted file mode 100644 index e2bfed27824..00000000000 --- a/components/expression_language/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -ExpressionLanguage -================== - -.. toctree:: - :maxdepth: 2 - - introduction - syntax - extending - caching diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst deleted file mode 100644 index 98b4402f7c7..00000000000 --- a/components/expression_language/introduction.rst +++ /dev/null @@ -1,115 +0,0 @@ -.. index:: - single: Expressions - Single: Components; Expression Language - -The ExpressionLanguage Component -================================ - - The ExpressionLanguage component provides an engine that can compile and - evaluate expressions. An expression is a one-liner that returns a value - (mostly, but not limited to, Booleans). - -Installation ------------- - -You can install the component in 2 different ways: - -* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/expression-language). - -How can the Expression Engine Help Me? --------------------------------------- - -The purpose of the component is to allow users to use expressions inside -configuration for more complex logic. For some examples, the Symfony2 Framework -uses expressions in security, for validation rules and in route matching. - -Besides using the component in the framework itself, the ExpressionLanguage -component is a perfect candidate for the foundation of a *business rule engine*. -The idea is to let the webmaster of a website configure things in a dynamic -way without using PHP and without introducing security problems: - -.. _component-expression-language-examples: - -.. code-block:: text - - # Get the special price if - user.getGroup() in ['good_customers', 'collaborator'] - - # Promote article to the homepage when - article.commentCount > 100 and article.category not in ["misc"] - - # Send an alert when - product.stock < 15 - -Expressions can be seen as a very restricted PHP sandbox and are immune to -external injections as you must explicitly declare which variables are available -in an expression. - -Usage ------ - -The ExpressionLanguage component can compile and evaluate expressions. -Expressions are one-liners that often return a Boolean, which can be used -by the code executing the expression in an ``if`` statement. A simple example -of an expression is ``1 + 2``. You can also use more complicated expressions, -such as ``someArray[3].someMethod('bar')``. - -The component provides 2 ways to work with expressions: - -* **evaluation**: the expression is evaluated without being compiled to PHP; -* **compile**: the expression is compiled to PHP, so it can be cached and - evaluated. - -The main class of the component is -:class:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage`:: - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - - $language = new ExpressionLanguage(); - - var_dump($language->evaluate('1 + 2')); // displays 3 - - var_dump($language->compile('1 + 2')); // displays (1 + 2) - -Expression Syntax ------------------ - -See :doc:`/components/expression_language/syntax` to learn the syntax of the -ExpressionLanguage component. - -Passing in Variables --------------------- - -You can also pass variables into the expression, which can be of any valid -PHP type (including objects):: - - use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - - $language = new ExpressionLanguage(); - - class Apple - { - public $variety; - } - - $apple = new Apple(); - $apple->variety = 'Honeycrisp'; - - var_dump($language->evaluate( - 'fruit.variety', - array( - 'fruit' => $apple, - ) - )); - -This will print "Honeycrisp". For more information, see the :doc:`/components/expression_language/syntax` -entry, especially :ref:`component-expression-objects` and :ref:`component-expression-arrays`. - -Caching -------- - -The component provides some different caching strategies, read more about them -in :doc:`/components/expression_language/caching`. - -.. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst deleted file mode 100644 index c3140ace7a2..00000000000 --- a/components/expression_language/syntax.rst +++ /dev/null @@ -1,310 +0,0 @@ -.. index:: - single: Syntax; ExpressionLanguage - -The Expression Syntax -===================== - -The ExpressionLanguage component uses a specific syntax which is based on the -expression syntax of Twig. In this document, you can find all supported -syntaxes. - -Supported Literals ------------------- - -The component supports: - -* **strings** - single and double quotes (e.g. ``'hello'``) -* **numbers** - e.g. ``103`` -* **arrays** - using JSON-like notation (e.g. ``[1, 2]``) -* **hashes** - using JSON-like notation (e.g. ``{ foo: 'bar' }``) -* **booleans** - ``true`` and ``false`` -* **null** - ``null`` - -.. caution:: - - A backslash (``\``) must be escaped by 4 backslashes (``\\\\``) in a string - and 8 backslashes (``\\\\\\\\``) in a regex:: - - echo $language->evaluate('"\\\\"'); // prints \ - $language->evaluate('"a\\\\b" matches "/^a\\\\\\\\b$/"'); // returns true - - Control characters (e.g. ``\n``) in expressions are replaced with - whitespace. To avoid this, escape the sequence with a single backslash - (e.g. ``\\n``). - -.. _component-expression-objects: - -Working with Objects --------------------- - -When passing objects into an expression, you can use different syntaxes to -access properties and call methods on the object. - -Accessing Public Properties -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Public properties on objects can be accessed by using the ``.`` syntax, similar -to JavaScript:: - - class Apple - { - public $variety; - } - - $apple = new Apple(); - $apple->variety = 'Honeycrisp'; - - var_dump($language->evaluate( - 'fruit.variety', - array( - 'fruit' => $apple, - ) - )); - -This will print out ``Honeycrisp``. - -Calling Methods -~~~~~~~~~~~~~~~ - -The ``.`` syntax can also be used to call methods on an object, similar to -JavaScript:: - - class Robot - { - public function sayHi($times) - { - $greetings = array(); - for ($i = 0; $i < $times; $i++) { - $greetings[] = 'Hi'; - } - - return implode(' ', $greetings).'!'; - } - } - - $robot = new Robot(); - - var_dump($language->evaluate( - 'robot.sayHi(3)', - array( - 'robot' => $robot, - ) - )); - -This will print out ``Hi Hi Hi!``. - -.. _component-expression-functions: - -Working with Functions ----------------------- - -You can also use registered functions in the expression by using the same -syntax as PHP and JavaScript. The ExpressionLanguage component comes with one -function by default: ``constant()``, which will return the value of the PHP -constant:: - - define('DB_USER', 'root'); - - var_dump($language->evaluate( - 'constant("DB_USER")' - )); - -This will print out ``root``. - -.. tip:: - - To read how to register your own functions to use in an expression, see - ":doc:`/components/expression_language/extending`". - -.. _component-expression-arrays: - -Working with Arrays -------------------- - -If you pass an array into an expression, use the ``[]`` syntax to access -array keys, similar to JavaScript:: - - $data = array('life' => 10, 'universe' => 10, 'everything' => 22); - - var_dump($language->evaluate( - 'data["life"] + data["universe"] + data["everything"]', - array( - 'data' => $data, - ) - )); - -This will print out ``42``. - -Supported Operators -------------------- - -The component comes with a lot of operators: - -Arithmetic Operators -~~~~~~~~~~~~~~~~~~~~ - -* ``+`` (addition) -* ``-`` (subtraction) -* ``*`` (multiplication) -* ``/`` (division) -* ``%`` (modulus) -* ``**`` (pow) - -For example:: - - var_dump($language->evaluate( - 'life + universe + everything', - array( - 'life' => 10, - 'universe' => 10, - 'everything' => 22, - ) - )); - -This will print out ``42``. - -Bitwise Operators -~~~~~~~~~~~~~~~~~ - -* ``&`` (and) -* ``|`` (or) -* ``^`` (xor) - -Comparison Operators -~~~~~~~~~~~~~~~~~~~~ - -* ``==`` (equal) -* ``===`` (identical) -* ``!=`` (not equal) -* ``!==`` (not identical) -* ``<`` (less than) -* ``>`` (greater than) -* ``<=`` (less than or equal to) -* ``>=`` (greater than or equal to) -* ``matches`` (regex match) - -.. tip:: - - To test if a string does *not* match a regex, use the logical ``not`` - operator in combination with the ``matches`` operator:: - - $language->evaluate('not ("foo" matches "/bar/")'); // returns true - - You must use parenthesis because the unary operator ``not`` has precedence - over the binary operator ``matches``. - -Examples:: - - $ret1 = $language->evaluate( - 'life == everything', - array( - 'life' => 10, - 'universe' => 10, - 'everything' => 22, - ) - ); - - $ret2 = $language->evaluate( - 'life > everything', - array( - 'life' => 10, - 'universe' => 10, - 'everything' => 22, - ) - ); - -Both variables would be set to ``false``. - -Logical Operators -~~~~~~~~~~~~~~~~~ - -* ``not`` or ``!`` -* ``and`` or ``&&`` -* ``or`` or ``||`` - -For example:: - - $ret = $language->evaluate( - 'life < universe or life < everything', - array( - 'life' => 10, - 'universe' => 10, - 'everything' => 22, - ) - ); - -This ``$ret`` variable will be set to ``true``. - -String Operators -~~~~~~~~~~~~~~~~ - -* ``~`` (concatenation) - -For example:: - - var_dump($language->evaluate( - 'firstName~" "~lastName', - array( - 'firstName' => 'Arthur', - 'lastName' => 'Dent', - ) - )); - -This would print out ``Arthur Dent``. - -Array Operators -~~~~~~~~~~~~~~~ - -* ``in`` (contain) -* ``not in`` (does not contain) - -For example:: - - class User - { - public $group; - } - - $user = new User(); - $user->group = 'human_resources'; - - $inGroup = $language->evaluate( - 'user.group in ["human_resources", "marketing"]', - array( - 'user' => $user, - ) - ); - -The ``$inGroup`` would evaluate to ``true``. - -Numeric Operators -~~~~~~~~~~~~~~~~~ - -* ``..`` (range) - -For example:: - - class User - { - public $age; - } - - $user = new User(); - $user->age = 34; - - $language->evaluate( - 'user.age in 18..45', - array( - 'user' => $user, - ) - ); - -This will evaluate to ``true``, because ``user.age`` is in the range from -``18`` to ``45``. - -Ternary Operators -~~~~~~~~~~~~~~~~~ - -* ``foo ? 'yes' : 'no'`` -* ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) -* ``foo ? 'yes'`` (equal to ``foo ? 'yes' : ''``) diff --git a/components/filesystem/introduction.rst b/components/filesystem.rst similarity index 92% rename from components/filesystem/introduction.rst rename to components/filesystem.rst index 53cbced419e..0ab9df9a021 100644 --- a/components/filesystem/introduction.rst +++ b/components/filesystem.rst @@ -6,6 +6,9 @@ The Filesystem Component The Filesystem component provides basic utilities for the filesystem. +.. versionadded:: 2.1 + The Filesystem component was introduced in Symfony 2.1. Previously, the + ``Filesystem`` class was located in the HttpKernel component. Installation ------------ @@ -24,14 +27,14 @@ The :class:`Symfony\\Component\\Filesystem\\Filesystem` class is the unique endpoint for filesystem operations:: use Symfony\Component\Filesystem\Filesystem; - use Symfony\Component\Filesystem\Exception\IOExceptionInterface; + use Symfony\Component\Filesystem\Exception\IOException; $fs = new Filesystem(); try { $fs->mkdir('/tmp/random/dir/'.mt_rand()); - } catch (IOExceptionInterface $e) { - echo "An error occurred while creating your directory at ".$e->getPath(); + } catch (IOException $e) { + echo "An error occurred while creating your directory"; } .. note:: @@ -235,6 +238,9 @@ isAbsolutePath dumpFile ~~~~~~~~ +.. versionadded:: 2.3 + The ``dumpFile()`` was introduced in Symfony 2.3. + :method:`Symfony\\Component\\Filesystem\\Filesystem::dumpFile` allows you to dump contents to a file. It does this in an atomic manner: it writes a temporary file first and then moves it to the new file location when it's finished. @@ -251,12 +257,14 @@ Error Handling -------------- Whenever something wrong happens, an exception implementing -:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` or -:class:`Symfony\\Component\\Filesystem\\Exception\\IOExceptionInterface` is thrown. +:class:`Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface` is +thrown. .. note:: - An :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is - thrown if directory creation fails. + Prior to version 2.1, ``mkdir`` returned a boolean and did not throw + exceptions. As of 2.1, a + :class:`Symfony\\Component\\Filesystem\\Exception\\IOException` is thrown + if a directory creation fails. .. _`Packagist`: https://packagist.org/packages/symfony/filesystem diff --git a/components/filesystem/index.rst b/components/filesystem/index.rst deleted file mode 100644 index e643f5a90f4..00000000000 --- a/components/filesystem/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -Filesystem -========== - -.. toctree:: - :maxdepth: 2 - - introduction - lock_handler diff --git a/components/filesystem/lock_handler.rst b/components/filesystem/lock_handler.rst deleted file mode 100644 index 90efe6b1033..00000000000 --- a/components/filesystem/lock_handler.rst +++ /dev/null @@ -1,82 +0,0 @@ -LockHandler -=========== - -What is a Lock? ---------------- - -File locking is a mechanism that restricts access to a computer file by allowing -only one user or process access at any specific time. This mechanism was -introduced a few decades ago for mainframes, but continues being useful for -modern applications. - -Symfony provides a LockHelper to help you use locks in your project. - -Usage ------ - -.. caution:: - - The lock handler only works if you're using just one server. If you have - several hosts, you must not use this helper. - -A lock can be used, for example, to allow only one instance of a command to run. - -.. code-block:: php - - use Symfony\Component\Filesystem\LockHandler; - - $lockHandler = new LockHandler('hello.lock'); - if (!$lockHandler->lock()) { - // the resource "hello" is already locked by another process - - return 0; - } - -The first argument of the constructor is a string that it will use as part of -the name of the file used to create the lock on the local filesystem. A best -practice for Symfony commands is to use the command name, such as ``acme:my-command``. -``LockHandler`` sanitizes the contents of the string before creating -the file, so you can pass any value for this argument. - -.. tip:: - - The ``.lock`` extension is optional, but it's a common practice to include - it. This will make it easier to find lock files on the filesystem. Moreover, - to avoid name collisions, ``LockHandler`` also appends a hash to the name of - the lock file. - -By default, the lock will be created in the temporary directory, but you can -optionally select the directory where locks are created by passing it as the -second argument of the constructor. - -The :method:`Symfony\\Component\\Filesystem\\LockHandler::lock` method tries to -acquire the lock. If the lock is acquired, the method returns ``true``, -``false`` otherwise. If the ``lock`` method is called several times on the same -instance it will always return ``true`` if the lock was acquired on the first -call. - -You can pass an optional blocking argument as the first argument to the -``lock()`` method, which defaults to ``false``. If this is set to ``true``, your -PHP code will wait indefinitely until the lock is released by another process. - -.. caution:: - - Be aware of the fact that the resource lock is automatically released as soon - as PHP applies the garbage-collection process to the ``LockHandler`` object. - This means that if you refactor the first example shown in this article as - follows:: - - use Symfony\Component\Filesystem\LockHandler; - - if (!(new LockHandler('hello.lock'))->lock()) { - // the resource "hello" is already locked by another process - - return 0; - } - - Now the code won't work as expected because PHP's garbage collection mechanism - removes the reference to the ``LockHandler`` object and thus, the lock is released - just after it's been created. - - Another alternative way to release the lock explicitly when needed is to use the - :method:`Symfony\\Component\\Filesystem\\LockHandler::release` method. diff --git a/components/finder.rst b/components/finder.rst index 2a12460031a..e8c70b3aabc 100644 --- a/components/finder.rst +++ b/components/finder.rst @@ -84,6 +84,9 @@ Search in several locations by chaining calls to $finder->files()->in(__DIR__)->in('/elsewhere'); +.. versionadded:: 2.2 + Wildcard support was introduced in version 2.2. + Use wildcard characters to search in the directories matching a pattern:: $finder->in('src/Symfony/*/*/Resources'); @@ -95,6 +98,10 @@ Exclude directories from matching with the $finder->in(__DIR__)->exclude('ruby'); +.. versionadded:: 2.3 + The :method:`Symfony\\Component\\Finder\\Finder::ignoreUnreadableDirs` + method was introduced in Symfony 2.3. + It's also possible to ignore directories that you don't have permission to read:: $finder->ignoreUnreadableDirs()->in(__DIR__); @@ -199,6 +206,9 @@ The ``notContains()`` method excludes files containing given pattern:: Path ~~~~ +.. versionadded:: 2.2 + The ``path()`` and ``notPath()`` methods were introduced in Symfony 2.2. + Restrict files and directories by path with the :method:`Symfony\\Component\\Finder\\Finder::path` method:: diff --git a/components/form/form_events.rst b/components/form/form_events.rst index 188d72c8460..d024cbdc3ea 100644 --- a/components/form/form_events.rst +++ b/components/form/form_events.rst @@ -257,6 +257,19 @@ Name ``FormEvents`` Constant Event's Data ``form.post_bind`` ``FormEvents::POST_SUBMIT`` View data ====================== ============================= =============== +.. versionadded:: 2.3 + Before Symfony 2.3, ``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT`` + and ``FormEvents::POST_SUBMIT`` were called ``FormEvents::PRE_BIND``, + ``FormEvents::BIND`` and ``FormEvents::POST_BIND``. + +.. caution:: + + The ``FormEvents::PRE_BIND``, ``FormEvents::BIND`` and + ``FormEvents::POST_BIND`` constants will be removed in version 3.0 of + Symfony. + The event names still keep their original values, so make sure you use the + ``FormEvents`` constants in your code for forward compatibility. + Event Listeners ~~~~~~~~~~~~~~~ @@ -268,13 +281,10 @@ Creating and binding an event listener to the form is very easy:: use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\CheckboxType; - use Symfony\Component\Form\Extension\Core\Type\EmailType; $form = $formFactory->createBuilder() - ->add('username', TextType::class) - ->add('show_email', CheckboxType::class) + ->add('username', 'text') + ->add('show_email', 'checkbox') ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { $user = $event->getData(); $form = $event->getForm(); @@ -287,7 +297,7 @@ Creating and binding an event listener to the form is very easy:: // If the data was submitted previously, the additional value that is // included in the request variables needs to be removed. if (true === $user['show_email']) { - $form->add('email', EmailType::class); + $form->add('email', 'email'); } else { unset($user['email']); $event->setData($user); @@ -300,17 +310,14 @@ Creating and binding an event listener to the form is very easy:: When you have created a form type class, you can use one of its methods as a callback for better readability:: - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\CheckboxType; - // ... class SubscriptionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { - $builder->add('username', TextType::class); - $builder->add('show_email', CheckboxType::class); + $builder->add('username', 'text'); + $builder->add('show_email', 'checkbox'); $builder->addEventListener( FormEvents::PRE_SET_DATA, array($this, 'onPreSetData') @@ -337,7 +344,6 @@ Event subscribers have different uses: use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; - use Symfony\Component\Form\Extension\Core\Type\EmailType; class AddEmailFieldListener implements EventSubscriberInterface { @@ -357,7 +363,7 @@ Event subscribers have different uses: // Check whether the user from the initial data has chosen to // display his email or not. if (true === $user->isShowEmail()) { - $form->add('email', EmailType::class); + $form->add('email', 'email'); } } @@ -374,7 +380,7 @@ Event subscribers have different uses: // If the data was submitted previously, the additional value that // is included in the request variables needs to be removed. if (true === $user['show_email']) { - $form->add('email', EmailType::class); + $form->add('email', 'email'); } else { unset($user['email']); $event->setData($user); @@ -384,14 +390,11 @@ Event subscribers have different uses: To register the event subscriber, use the addEventSubscriber() method:: - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\CheckboxType; - // ... $form = $formFactory->createBuilder() - ->add('username', TextType::class) - ->add('show_email', CheckboxType::class) + ->add('username', 'text') + ->add('show_email', 'checkbox') ->addEventSubscriber(new AddEmailFieldListener()) ->getForm(); diff --git a/components/form/introduction.rst b/components/form/introduction.rst index 6ff900cddfa..67de784bdfb 100644 --- a/components/form/introduction.rst +++ b/components/form/introduction.rst @@ -68,6 +68,9 @@ factory. Request Handling ~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + The ``handleRequest()`` method was introduced in Symfony 2.3. + To process form data, you'll need to call the :method:`Symfony\\Component\\Form\\Form::handleRequest` method:: @@ -110,45 +113,45 @@ CSRF Protection ~~~~~~~~~~~~~~~ Protection against CSRF attacks is built into the Form component, but you need -to explicitly enable it or replace it with a custom solution. If you want to -use the built-in support, require the Security CSRF component by executing -``composer require symfony/security-csrf``. - -The following snippet adds CSRF protection to the form factory:: +to explicitly enable it or replace it with a custom solution. The following +snippet adds CSRF protection to the form factory:: use Symfony\Component\Form\Forms; + use Symfony\Component\Form\Extension\Csrf\CsrfExtension; + use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; use Symfony\Component\HttpFoundation\Session\Session; - use Symfony\Component\Security\Extension\Csrf\CsrfExtension; - use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage; - use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator; - use Symfony\Component\Security\Csrf\CsrfTokenManager; + + // generate a CSRF secret from somewhere + $csrfSecret = ''; // create a Session object from the HttpFoundation component $session = new Session(); - $csrfGenerator = new UriSafeTokenGenerator(); - $csrfStorage = new SessionTokenStorage($session); - $csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage); + $csrfProvider = new SessionCsrfProvider($session, $csrfSecret); $formFactory = Forms::createFormFactoryBuilder() // ... - ->addExtension(new CsrfExtension($csrfStorage)) + ->addExtension(new CsrfExtension($csrfProvider)) ->getFormFactory(); +To secure your application against CSRF attacks, you need to define a CSRF +secret. Generate a random string with at least 32 characters, insert it in the +above snippet and make sure that nobody except your web server can access +the secret. + Internally, this extension will automatically add a hidden field to every -form (called ``_token`` by default) whose value is automatically generated by -the CSRF generator and validated when binding the form. +form (called ``_token`` by default) whose value is automatically generated +and validated when binding the form. .. tip:: If you're not using the HttpFoundation component, you can use - :class:`Symfony\\Component\\Security\\Csrf\\TokenStorage\\NativeSessionTokenStorage` + :class:`Symfony\\Component\\Form\\Extension\\Csrf\\CsrfProvider\\DefaultCsrfProvider` instead, which relies on PHP's native session handling:: - use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage; + use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; - $csrfStorage = new NativeSessionTokenStorage(); - // ... + $csrfProvider = new DefaultCsrfProvider($csrfSecret); Twig Templating ~~~~~~~~~~~~~~~ @@ -160,14 +163,14 @@ component offers a rich integration. To use the integration, you'll need the ``TwigBridge``, which provides integration between Twig and several Symfony components. If you're using Composer, you -could install the latest 3.x version by adding the following ``require`` +could install the latest 2.3 version by adding the following ``require`` line to your ``composer.json`` file: .. code-block:: json { "require": { - "symfony/twig-bridge": "~3.0" + "symfony/twig-bridge": "2.3.*" } } @@ -240,15 +243,15 @@ via your own Twig extension. To use the built-in integration, be sure that your project has Symfony's Translation and :doc:`Config ` components -installed. If you're using Composer, you could get the latest 3.x version +installed. If you're using Composer, you could get the latest 2.3 version of each of these by adding the following to your ``composer.json`` file: .. code-block:: json { "require": { - "symfony/translation": "~3.0", - "symfony/config": "~3.0" + "symfony/translation": "2.3.*", + "symfony/config": "2.3.*" } } @@ -292,13 +295,13 @@ array or object) and pass it through your own validation system. To use the integration with Symfony's Validator component, first make sure it's installed in your application. If you're using Composer and want to -install the latest 3.x version, add this to your ``composer.json``: +install the latest 2.3 version, add this to your ``composer.json``: .. code-block:: json { "require": { - "symfony/validator": "~3.0" + "symfony/validator": "2.3.*" } } @@ -315,8 +318,9 @@ Your integration with the Validation component will look something like this:: use Symfony\Component\Validator\Validation; $vendorDir = realpath(__DIR__.'/../vendor'); - $vendorFormDir = $vendorDir.'/symfony/form'; - $vendorValidatorDir = $vendorDir.'/symfony/validator'; + $vendorFormDir = $vendorDir.'/symfony/form/Symfony/Component/Form'; + $vendorValidatorDir = + $vendorDir.'/symfony/validator/Symfony/Component/Validator'; // create the validator - details will vary $validator = Validation::createValidator(); @@ -387,14 +391,9 @@ is created from the form factory. .. code-block:: php-standalone - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - - // ... - $form = $formFactory->createBuilder() - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); var_dump($twig->render('new.html.twig', array( @@ -408,8 +407,6 @@ is created from the form factory. use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; class DefaultController extends Controller { @@ -417,10 +414,9 @@ is created from the form factory. { // createFormBuilder is a shortcut to get the "form factory" // and then call "createBuilder()" on it - $form = $this->createFormBuilder() - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); return $this->render('AcmeTaskBundle:Default:new.html.twig', array( @@ -431,8 +427,8 @@ is created from the form factory. As you can see, creating a form is like writing a recipe: you call ``add`` for each new field you want to create. The first argument to ``add`` is the -name of your field, and the second is the fully qualified class name. The Form -component comes with a lot of :doc:`built-in types `. +name of your field, and the second is the field "type". The Form component +comes with a lot of :doc:`built-in types `. Now that you've built your form, learn how to :ref:`render ` it and :ref:`process the form submission `. @@ -448,35 +444,24 @@ builder: .. code-block:: php-standalone - use Symfony\Component\Form\Extension\Core\Type\FormType; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - - // ... - $defaults = array( 'dueDate' => new \DateTime('tomorrow'), ); - $form = $formFactory->createBuilder(FormType::class, $defaults) - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + $form = $formFactory->createBuilder('form', $defaults) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); .. code-block:: php-symfony - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - - // ... - $defaults = array( 'dueDate' => new \DateTime('tomorrow'), ); $form = $this->createFormBuilder($defaults) - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); .. tip:: @@ -515,6 +500,10 @@ to do that in the ":ref:`form-rendering-template`" section. Changing a Form's Method and Action ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. versionadded:: 2.3 + The ability to configure the form method and action was introduced in + Symfony 2.3. + By default, a form is submitted to the same URI that rendered the form with an HTTP POST request. This behavior can be changed using the :ref:`form-option-action` and :ref:`form-option-method` options (the ``method`` option is also used @@ -524,11 +513,7 @@ by ``handleRequest()`` to determine whether a form has been submitted): .. code-block:: php-standalone - use Symfony\Component\Form\Extension\Core\Type\FormType; - - // ... - - $formBuilder = $formFactory->createBuilder(FormType::class, null, array( + $formBuilder = $formFactory->createBuilder('form', null, array( 'action' => '/search', 'method' => 'GET', )); @@ -537,8 +522,6 @@ by ``handleRequest()`` to determine whether a form has been submitted): .. code-block:: php-symfony - use Symfony\Component\Form\Extension\Core\Type\FormType; - // ... public function searchAction() @@ -565,14 +548,10 @@ method: use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - - // ... $form = $formFactory->createBuilder() - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); $request = Request::createFromGlobals(); @@ -594,16 +573,13 @@ method: .. code-block:: php-symfony - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; - // ... public function newAction(Request $request) { $form = $this->createFormBuilder() - ->add('task', TextType::class) - ->add('dueDate', DateType::class) + ->add('task', 'text') + ->add('dueDate', 'date') ->getForm(); $form->handleRequest($request); @@ -613,7 +589,7 @@ method: // ... perform some action, such as saving the data to the database - return $this->redirectToRoute('task_success'); + return $this->redirect($this->generateUrl('task_success')); } // ... @@ -648,14 +624,12 @@ option when building each field: use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Type; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; $form = $formFactory->createBuilder() - ->add('task', TextType::class, array( + ->add('task', 'text', array( 'constraints' => new NotBlank(), )) - ->add('dueDate', DateType::class, array( + ->add('dueDate', 'date', array( 'constraints' => array( new NotBlank(), new Type('\DateTime'), @@ -667,14 +641,12 @@ option when building each field: use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Type; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\DateType; $form = $this->createFormBuilder() - ->add('task', TextType::class, array( + ->add('task', 'text', array( 'constraints' => new NotBlank(), )) - ->add('dueDate', DateType::class, array( + ->add('dueDate', 'date', array( 'constraints' => array( new NotBlank(), new Type('\DateTime'), @@ -694,27 +666,30 @@ Accessing Form Errors ~~~~~~~~~~~~~~~~~~~~~ You can use the :method:`Symfony\\Component\\Form\\FormInterface::getErrors` -method to access the list of errors. It returns a -:class:`Symfony\\Component\\Form\\FormErrorIterator` instance:: +method to access the list of errors. Each element is a :class:`Symfony\\Component\\Form\\FormError` +object:: $form = ...; // ... - // a FormErrorIterator instance, but only errors attached to this + // an array of FormError objects, but only errors attached to this // form level (e.g. "global errors) $errors = $form->getErrors(); - // a FormErrorIterator instance, but only errors attached to the + // an array of FormError objects, but only errors attached to the // "firstName" field $errors = $form['firstName']->getErrors(); - // a FormErrorIterator instance in a flattened structure - // use getOrigin() to determine the form causing the error - $errors = $form->getErrors(true); + // a string representation of all errors of the whole form tree + $errors = $form->getErrorsAsString(); + +.. note:: - // a FormErrorIterator instance representing the form tree structure - $errors = $form->getErrors(true, false); + If you enable the :ref:`error_bubbling ` + option on a field, calling ``getErrors()`` on the parent form will include + errors from that field. However, there is no way to determine which field + an error was originally attached to. .. _Packagist: https://packagist.org/packages/symfony/form .. _Twig: http://twig.sensiolabs.org diff --git a/components/form/type_guesser.rst b/components/form/type_guesser.rst index 78fa338a814..13a64400118 100644 --- a/components/form/type_guesser.rst +++ b/components/form/type_guesser.rst @@ -32,9 +32,11 @@ This interface requires 4 methods: tries to guess the value of the :ref:`required ` option; * :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessMaxLength` - - tries to guess the value of the ``maxlength`` input attribute; + tries to guess the value of the :ref:`max_length ` + option; * :method:`Symfony\\Component\\Form\\FormTypeGuesserInterface::guessPattern` - - tries to guess the value of the ``pattern`` input attribute. + tries to guess the value of the :ref:`pattern ` + option. Start by creating the class and these methods. Next, you'll learn how to fill each on. @@ -89,10 +91,6 @@ With this knowledge, you can easily implement the ``guessType`` method of the use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; - use Symfony\Component\Form\Extension\Core\Type\TextType; - use Symfony\Component\Form\Extension\Core\Type\IntegerType; - use Symfony\Component\Form\Extension\Core\Type\NumberType; - use Symfony\Component\Form\Extension\Core\Type\CheckboxType; class PHPDocTypeGuesser implements FormTypeGuesserInterface { @@ -109,25 +107,25 @@ With this knowledge, you can easily implement the ``guessType`` method of the case 'string': // there is a high confidence that the type is text when // @var string is used - return new TypeGuess(TextType::class, array(), Guess::HIGH_CONFIDENCE); + return new TypeGuess('text', array(), Guess::HIGH_CONFIDENCE); case 'int': case 'integer': // integers can also be the id of an entity or a checkbox (0 or 1) - return new TypeGuess(IntegerType::class, array(), Guess::MEDIUM_CONFIDENCE); + return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case 'float': case 'double': case 'real': - return new TypeGuess(NumberType::class, array(), Guess::MEDIUM_CONFIDENCE); + return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': case 'bool': - return new TypeGuess(CheckboxType::class, array(), Guess::HIGH_CONFIDENCE); + return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE); default: // there is a very low confidence that this one is correct - return new TypeGuess(TextType::class, array(), Guess::LOW_CONFIDENCE); + return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } } diff --git a/components/http_foundation/introduction.rst b/components/http_foundation/introduction.rst index 6f6c6ccc5eb..2cbae21727c 100644 --- a/components/http_foundation/introduction.rst +++ b/components/http_foundation/introduction.rst @@ -125,12 +125,6 @@ has some methods to filter the input values: :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::getAlnum` Returns the alphabetic characters and digits of the parameter value; -:method:`Symfony\\Component\\HttpFoundation\\ParameterBag::getBoolean` - Returns the parameter value converted to boolean; - - .. versionadded:: 2.6 - The ``getBoolean()`` method was introduced in Symfony 2.6. - :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::getDigits` Returns the digits of the parameter value; @@ -140,35 +134,39 @@ has some methods to filter the input values: :method:`Symfony\\Component\\HttpFoundation\\ParameterBag::filter` Filters the parameter by using the PHP :phpfunction:`filter_var` function. -All getters take up to two arguments: the first one is the parameter name +All getters take up to three arguments: the first one is the parameter name and the second one is the default value to return if the parameter does not exist:: // the query string is '?foo=bar' $request->query->get('foo'); - // returns 'bar' + // returns bar $request->query->get('bar'); // returns null - $request->query->get('bar', 'baz'); - // returns 'baz' + $request->query->get('bar', 'bar'); + // returns 'bar' When PHP imports the request query, it handles request parameters like ``foo[bar]=bar`` in a special way as it creates an array. So you can get the -``foo`` parameter and you will get back an array with a ``bar`` element:: +``foo`` parameter and you will get back an array with a ``bar`` element. But +sometimes, you might want to get the value for the "original" parameter name: +``foo[bar]``. This is possible with all the ``ParameterBag`` getters like +:method:`Symfony\\Component\\HttpFoundation\\Request::get` via the third +argument:: - // the query string is '?foo[bar]=baz' + // the query string is '?foo[bar]=bar' $request->query->get('foo'); - // returns array('bar' => 'baz') + // returns array('bar' => 'bar') $request->query->get('foo[bar]'); // returns null - $request->query->get('foo')['bar']; - // returns 'baz' + $request->query->get('foo[bar]', null, true); + // returns 'bar' .. _component-foundation-attributes: @@ -254,8 +252,9 @@ by using the following methods: :method:`Symfony\\Component\\HttpFoundation\\Request::getCharsets` Returns the list of accepted charsets ordered by descending quality. -:method:`Symfony\\Component\\HttpFoundation\\Request::getEncodings` - Returns the list of accepted encodings ordered by descending quality. +.. versionadded:: 2.2 + The :class:`Symfony\\Component\\HttpFoundation\\AcceptHeader` class was + introduced in Symfony 2.2. If you need to get full access to parsed data from ``Accept``, ``Accept-Language``, ``Accept-Charset`` or ``Accept-Encoding``, you can use @@ -282,38 +281,6 @@ request information. Have a look at :class:`the Request API ` for more information about them. -Overriding the Request -~~~~~~~~~~~~~~~~~~~~~~ - -The ``Request`` class should not be overridden as it is a data object that -represents an HTTP message. But when moving from a legacy system, adding -methods or changing some default behavior might help. In that case, register a -PHP callable that is able to create an instance of your ``Request`` class:: - - use Symfony\Component\HttpFoundation\Request; - - Request::setFactory(function ( - array $query = array(), - array $request = array(), - array $attributes = array(), - array $cookies = array(), - array $files = array(), - array $server = array(), - $content = null - ) { - return SpecialRequest::create( - $query, - $request, - $attributes, - $cookies, - $files, - $server, - $content - ); - }); - - $request = Request::createFromGlobals(); - .. _component-http-foundation-response: Response @@ -328,7 +295,7 @@ code, and an array of HTTP headers:: $response = new Response( 'Content', - Response::HTTP_OK, + 200, array('content-type' => 'text/html') ); @@ -339,7 +306,7 @@ This information can also be manipulated after the Response object creation:: // the headers public attribute is a ResponseHeaderBag $response->headers->set('Content-Type', 'text/plain'); - $response->setStatusCode(Response::HTTP_NOT_FOUND); + $response->setStatusCode(404); When setting the ``Content-Type`` of the Response, you can set the charset, but it is better to set it via the @@ -486,6 +453,10 @@ abstracts the hard work behind a simple API:: $response->headers->set('Content-Disposition', $d); +.. versionadded:: 2.2 + The :class:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse` + class was introduced in Symfony 2.2. + Alternatively, if you are serving a static file, you can use a :class:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse`:: @@ -512,6 +483,9 @@ or change its ``Content-Disposition``:: 'filename.txt' ); +.. versionadded:: 2.6 + The ``deleteFileAfterSend()`` method was introduced in Symfony 2.6. + It is possible to delete the file after the request is sent with the :method:`Symfony\\Component\\HttpFoundation\\BinaryFileResponse::deleteFileAfterSend` method. Please note that this will not work when the ``X-Sendfile`` header is set. diff --git a/components/http_foundation/trusting_proxies.rst b/components/http_foundation/trusting_proxies.rst index a8c0193668d..fbe9b30cdee 100644 --- a/components/http_foundation/trusting_proxies.rst +++ b/components/http_foundation/trusting_proxies.rst @@ -19,6 +19,10 @@ Since HTTP headers can be spoofed, Symfony does *not* trust these proxy headers by default. If you are behind a proxy, you should manually whitelist your proxy. +.. versionadded:: 2.3 + CIDR notation support was introduced in Symfony 2.3, so you can whitelist whole + subnets (e.g. ``10.0.0.0/8``, ``fc00::/7``). + .. code-block:: php use Symfony\Component\HttpFoundation\Request; diff --git a/components/http_kernel/introduction.rst b/components/http_kernel/introduction.rst index fd4682a9a53..1a808980b5e 100644 --- a/components/http_kernel/introduction.rst +++ b/components/http_kernel/introduction.rst @@ -592,17 +592,16 @@ each event has their own event object: .. _component-http-kernel-event-table: -===================== ================================ =================================================================================== -Name ``KernelEvents`` Constant Argument passed to the listener -===================== ================================ =================================================================================== -kernel.request ``KernelEvents::REQUEST`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent` -kernel.controller ``KernelEvents::CONTROLLER`` :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` -kernel.view ``KernelEvents::VIEW`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent` -kernel.response ``KernelEvents::RESPONSE`` :class:`Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent` -kernel.finish_request ``KernelEvents::FINISH_REQUEST`` :class:`Symfony\\Component\\HttpKernel\\Event\\FinishRequestEvent` -kernel.terminate ``KernelEvents::TERMINATE`` :class:`Symfony\\Component\\HttpKernel\\Event\\PostResponseEvent` -kernel.exception ``KernelEvents::EXCEPTION`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent` -===================== ================================ =================================================================================== +================= ============================ =================================================================================== +Name ``KernelEvents`` Constant Argument Passed to the Listener +================= ============================ =================================================================================== +kernel.request ``KernelEvents::REQUEST`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent` +kernel.controller ``KernelEvents::CONTROLLER`` :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` +kernel.view ``KernelEvents::VIEW`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent` +kernel.response ``KernelEvents::RESPONSE`` :class:`Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent` +kernel.terminate ``KernelEvents::TERMINATE`` :class:`Symfony\\Component\\HttpKernel\\Event\\PostResponseEvent` +kernel.exception ``KernelEvents::EXCEPTION`` :class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent` +================= ============================ =================================================================================== .. _http-kernel-working-example: @@ -616,7 +615,6 @@ However, the HttpKernel component comes with some built-in listeners and a built-in ControllerResolver that can be used to create a working example:: use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -642,7 +640,7 @@ a built-in ControllerResolver that can be used to create a working example:: $matcher = new UrlMatcher($routes, new RequestContext()); $dispatcher = new EventDispatcher(); - $dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack())); + $dispatcher->addSubscriber(new RouterListener($matcher)); $resolver = new ControllerResolver(); $kernel = new HttpKernel($dispatcher, $resolver); @@ -687,8 +685,8 @@ This creates another full request-response cycle where this new ``Request`` is transformed into a ``Response``. The only difference internally is that some listeners (e.g. security) may only act upon the master request. Each listener is passed some sub-class of :class:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent`, -whose :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::isMasterRequest` -can be used to check if the current request is a "master" or "sub" request. +whose :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequestType` +can be used to figure out if the current request is a "master" or "sub" request. For example, a listener that only needs to act on the master request may look like this:: @@ -698,7 +696,7 @@ look like this:: public function onKernelRequest(GetResponseEvent $event) { - if (!$event->isMasterRequest()) { + if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } diff --git a/components/index.rst b/components/index.rst index 43aa14e5e40..780b33b2c9e 100644 --- a/components/index.rst +++ b/components/index.rst @@ -5,25 +5,22 @@ The Components :hidden: using_components - asset/index browser_kit/index class_loader/index config/index console/index css_selector - debug/index + debug dependency_injection/index dom_crawler event_dispatcher/index - expression_language/index - filesystem/index + filesystem finder form/index http_foundation/index http_kernel/index intl options_resolver - phpunit_bridge process property_access/index routing/index @@ -32,7 +29,6 @@ The Components stopwatch templating/index translation/index - var_dumper/index yaml/index .. include:: /components/map.rst.inc diff --git a/components/intl.rst b/components/intl.rst index d7282cf0d14..b8047db0cd0 100644 --- a/components/intl.rst +++ b/components/intl.rst @@ -8,6 +8,10 @@ The Intl Component A PHP replacement layer for the C `intl extension`_ that also provides access to the localization data of the `ICU library`_. +.. versionadded:: 2.3 + The Intl component was introduced in Symfony 2.3. In earlier versions of Symfony, + you should use the Locale component instead. + .. caution:: The replacement layer is limited to the locale "en". If you want to use @@ -56,6 +60,87 @@ code:: $loader->registerPrefixFallback('/path/to/Icu/Resources/stubs'); } +.. sidebar:: ICU and Deployment Problems + + .. note:: + + These deployment problems only affect the following Symfony versions: + 2.3.0 to 2.3.20 versions, any 2.4.x version and 2.5.0 to 2.5.5 versions. + + The intl extension internally uses the `ICU library`_ to obtain localization + data such as number formats in different languages, country names and more. + To make this data accessible to userland PHP libraries, Symfony ships a copy + in the `Icu component`_. + + Depending on the ICU version compiled with your intl extension, a matching + version of that component needs to be installed. It sounds complicated, + but usually Composer does this for you automatically: + + * 1.0.*: when the intl extension is not available + * 1.1.*: when intl is compiled with ICU 4.0 or higher + * 1.2.*: when intl is compiled with ICU 4.4 or higher + + These versions are important when you deploy your application to a **server with + a lower ICU version** than your development machines, because deployment will + fail if: + + * the development machines are compiled with ICU 4.4 or higher, but the + server is compiled with a lower ICU version than 4.4; + * the intl extension is available on the development machines but not on + the server. + + For example, consider that your development machines ship ICU 4.8 and the server + ICU 4.2. When you run ``composer update`` on the development machine, version + 1.2.* of the Icu component will be installed. But after deploying the + application, ``composer install`` will fail with the following error: + + .. code-block:: bash + + $ composer install + Loading composer repositories with package information + Installing dependencies from lock file + Your requirements could not be resolved to an installable set of packages. + + Problem 1 + - symfony/icu 1.2.x requires lib-icu >=4.4 -> the requested linked + library icu has the wrong version installed or is missing from your + system, make sure to have the extension providing it. + + The error tells you that the requested version of the Icu component, version + 1.2, is not compatible with PHP's ICU version 4.2. + + One solution to this problem is to run ``composer update`` instead of + ``composer install``. It is highly recommended **not** to do this. The + ``update`` command will install the latest versions of each Composer dependency + to your production server and potentially break the application. + + A better solution is to fix your composer.json to the version required by the + production server. First, determine the ICU version on the server: + + .. code-block:: bash + + $ php -i | grep ICU + ICU version => 4.2.1 + + Then fix the Icu component in your ``composer.json`` file to a matching version: + + .. code-block:: json + + { + "require": { + "symfony/icu": "1.1.*" + } + } + + Set the version to + + * "1.0.*" if the server does not have the intl extension installed; + * "1.1.*" if the server is compiled with ICU 4.2 or lower. + + Finally, run ``composer update symfony/icu`` on your development machine, test + extensively and deploy again. The installation of the dependencies will now + succeed. + Writing and Reading Resource Bundles ------------------------------------ diff --git a/components/map.rst.inc b/components/map.rst.inc index deb5d6b84c8..b69b347373f 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -1,20 +1,16 @@ * :doc:`/components/using_components` -* :doc:`/components/asset/index` - - * :doc:`/components/asset/introduction` - * :doc:`/components/browser_kit/index` - + * :doc:`/components/browser_kit/introduction` * :doc:`/components/class_loader/index` * :doc:`/components/class_loader/introduction` * :doc:`/components/class_loader/class_loader` - * :doc:`/components/class_loader/psr4_class_loader` * :doc:`/components/class_loader/map_class_loader` * :doc:`/components/class_loader/cache_class_loader` + * :doc:`/components/class_loader/debug_class_loader` * :doc:`/components/class_loader/class_map_generator` * :doc:`/components/config/index` @@ -29,20 +25,17 @@ * :doc:`/components/console/introduction` * :doc:`/components/console/usage` * :doc:`/components/console/single_command_tool` - * :doc:`/components/console/changing_default_command` * :doc:`/components/console/console_arguments` * :doc:`/components/console/events` - * :doc:`/components/console/logger` * :doc:`/components/console/helpers/index` * **CssSelector** * :doc:`/components/css_selector` -* :doc:`/components/debug/index` +* **Debug** - * :doc:`/components/debug/introduction` - * :doc:`/components/debug/class_loader` + * :doc:`/components/debug` * :doc:`/components/dependency_injection/index` @@ -50,7 +43,6 @@ * :doc:`/components/dependency_injection/types` * :doc:`/components/dependency_injection/parameters` * :doc:`/components/dependency_injection/definitions` - * :doc:`/components/dependency_injection/autowiring` * :doc:`/components/dependency_injection/synthetic_services` * :doc:`/components/dependency_injection/compilation` * :doc:`/components/dependency_injection/tags` @@ -73,17 +65,9 @@ * :doc:`/components/event_dispatcher/immutable_dispatcher` * :doc:`/components/event_dispatcher/traceable_dispatcher` -* :doc:`/components/expression_language/index` - - * :doc:`/components/expression_language/introduction` - * :doc:`/components/expression_language/syntax` - * :doc:`/components/expression_language/extending` - * :doc:`/components/expression_language/caching` - -* :doc:`/components/filesystem/index` +* **Filesystem** - * :doc:`/components/filesystem/introduction` - * :doc:`/components/filesystem/lock_handler` + * :doc:`/components/filesystem` * **Finder** @@ -116,10 +100,6 @@ * :doc:`/components/options_resolver` -* **PHPUnitBridge** - - * :doc:`/components/phpunit_bridge` - * **Process** * :doc:`/components/process` @@ -159,11 +139,6 @@ * :doc:`/components/translation/usage` * :doc:`/components/translation/custom_formats` -* :doc:`/components/var_dumper/index` - - * :doc:`/components/var_dumper/introduction` - * :doc:`/components/var_dumper/advanced` - * :doc:`/components/yaml/index` * :doc:`/components/yaml/introduction` diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 4c0bb039e55..c835d16b50a 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -5,9 +5,8 @@ The OptionsResolver Component ============================= - The OptionsResolver component is :phpfunction:`array_replace` on steroids. - It allows you to create an options system with required options, defaults, - validation (type, value), normalization and more. + The OptionsResolver component helps you configure objects with option + arrays. It supports default values, option constraints and lazy options. Installation ------------ @@ -19,14 +18,14 @@ You can install the component in 2 different ways: .. include:: /components/require_autoload.rst.inc -Notes on Previous Versions --------------------------- - Usage ----- -Imagine you have a ``Mailer`` class which has four options: ``host``, -``username``, ``password`` and ``port``:: +Imagine you have a ``Mailer`` class which has 2 options: ``host`` and +``password``. These options are going to be handled by the OptionsResolver +Component. + +First, create the ``Mailer`` class:: class Mailer { @@ -34,131 +33,71 @@ Imagine you have a ``Mailer`` class which has four options: ``host``, public function __construct(array $options = array()) { - $this->options = $options; } } -When accessing the ``$options``, you need to add a lot of boilerplate code to -check which options are set:: - - class Mailer - { - // ... - public function sendMail($from, $to) - { - $mail = ...; - - $mail->setHost(isset($this->options['host']) - ? $this->options['host'] - : 'smtp.example.org'); - - $mail->setUsername(isset($this->options['username']) - ? $this->options['username'] - : 'user'); +You could of course set the ``$options`` value directly on the property. Instead, +use the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` class +and let it resolve the options by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::resolve`. +The advantages of doing this will become more obvious as you continue:: - $mail->setPassword(isset($this->options['password']) - ? $this->options['password'] - : 'pa$$word'); - - $mail->setPort(isset($this->options['port']) - ? $this->options['port'] - : 25); - - // ... - } - } - -This boilerplate is hard to read and repetitive. Also, the default values of the -options are buried in the business logic of your code. Use the -:phpfunction:`array_replace` to fix that:: + use Symfony\Component\OptionsResolver\OptionsResolver; - class Mailer + // ... + public function __construct(array $options = array()) { - // ... + $resolver = new OptionsResolver(); - public function __construct(array $options = array()) - { - $this->options = array_replace(array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - ), $options); - } + $this->options = $resolver->resolve($options); } -Now all four options are guaranteed to be set. But what happens if the user of -the ``Mailer`` class makes a mistake? - -.. code-block:: php - - $mailer = new Mailer(array( - 'usernme' => 'johndoe', // usernAme misspelled - )); +The options property now is a well defined array with all resolved options +readily available:: -No error will be shown. In the best case, the bug will appear during testing, -but the developer will spend time looking for the problem. In the worst case, -the bug might not appear until it's deployed to the live system. - -Fortunately, the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` -class helps you to fix this problem:: - - use Symfony\Component\OptionsResolver\OptionsResolver; - - class Mailer + // ... + public function sendMail($from, $to) { + $mail = ...; + $mail->setHost($this->options['host']); + $mail->setUsername($this->options['username']); + $mail->setPassword($this->options['password']); // ... - - public function __construct(array $options = array()) - { - $resolver = new OptionsResolver(); - $resolver->setDefaults(array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - )); - - $this->options = $resolver->resolve($options); - } } -Like before, all options will be guaranteed to be set. Additionally, an -:class:`Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException` -is thrown if an unknown option is passed:: +Configuring the OptionsResolver +------------------------------- + +Now, try to actually use the class:: $mailer = new Mailer(array( - 'usernme' => 'johndoe', + 'host' => 'smtp.example.org', + 'username' => 'user', + 'password' => 'pa$$word', )); - // UndefinedOptionsException: The option "usernme" does not exist. - // Known options are: "host", "password", "port", "username" +Right now, you'll receive a +:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException`, +which tells you that the options ``host`` and ``password`` do not exist. +This is because you need to configure the ``OptionsResolver`` first, so it +knows which options should be resolved. -The rest of your code can access the values of the options without boilerplate -code:: +.. tip:: - // ... - class Mailer - { - // ... + To check if an option exists, you can use the + :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isKnown` + function. - public function sendMail($from, $to) - { - $mail = ...; - $mail->setHost($this->options['host']); - $mail->setUsername($this->options['username']); - $mail->setPassword($this->options['password']); - $mail->setPort($this->options['port']); - // ... - } - } +A best practice is to put the configuration in a method (e.g. +``configureOptions``). You call this method in the constructor to configure +the ``OptionsResolver`` class:: -It's a good practice to split the option configuration into a separate method:: + use Symfony\Component\OptionsResolver\OptionsResolver; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; - // ... class Mailer { - // ... + protected $options; public function __construct(array $options = array()) { @@ -168,525 +107,300 @@ It's a good practice to split the option configuration into a separate method:: $this->options = $resolver->resolve($options); } - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefaults(array( - 'host' => 'smtp.example.org', - 'username' => 'user', - 'password' => 'pa$$word', - 'port' => 25, - 'encryption' => null, - )); - } - } - -First, your code becomes easier to read, especially if the constructor does more -than processing options. Second, sub-classes may now override the -``configureOptions()`` method to adjust the configuration of the options:: - - // ... - class GoogleMailer extends Mailer - { - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - $resolver->setDefaults(array( - 'host' => 'smtp.google.com', - 'encryption' => 'ssl', - )); - } - } - -Required Options -~~~~~~~~~~~~~~~~ - -If an option must be set by the caller, pass that option to -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`. -For example, to make the ``host`` option required, you can do:: - - // ... - class Mailer - { - // ... - - public function configureOptions(OptionsResolver $resolver) + protected function configureOptions(OptionsResolverInterface $resolver) { - // ... - $resolver->setRequired('host'); + // ... configure the resolver, you will learn this + // in the sections below } } -If you omit a required option, a -:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` -will be thrown:: - - $mailer = new Mailer(); - - // MissingOptionsException: The required option "host" is missing. - -The :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired` -method accepts a single name or an array of option names if you have more than -one required option:: - - // ... - class Mailer - { - // ... - - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setRequired(array('host', 'username', 'password')); - } - } - -Use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` to find -out if an option is required. You can use -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getRequiredOptions` to -retrieve the names of all required options:: - - // ... - class GoogleMailer extends Mailer - { - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - if ($resolver->isRequired('host')) { - // ... - } - - $requiredOptions = $resolver->getRequiredOptions(); - } - } - -If you want to check whether a required option is still missing from the default -options, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isMissing`. -The difference between this and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` -is that this method will return false if a required option has already -been set:: - - // ... - class Mailer - { - // ... - - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setRequired('host'); - } - } - - // ... - class GoogleMailer extends Mailer - { - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - $resolver->isRequired('host'); - // => true - - $resolver->isMissing('host'); - // => true - - $resolver->setDefault('host', 'smtp.google.com'); - - $resolver->isRequired('host'); - // => true - - $resolver->isMissing('host'); - // => false - } - } - -The method :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getMissingOptions` -lets you access the names of all missing options. +Set default Values +~~~~~~~~~~~~~~~~~~ -Type Validation -~~~~~~~~~~~~~~~ - -You can run additional checks on the options to make sure they were passed -correctly. To validate the types of the options, call -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`:: +Most of the options have a default value. You can configure these options by +calling :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefaults`:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setAllowedTypes('host', 'string'); - $resolver->setAllowedTypes('port', array('null', 'int')); - } + $resolver->setDefaults(array( + 'username' => 'root', + )); } -For each option, you can define either just one type or an array of acceptable -types. You can pass any type for which an ``is_()`` function is defined -in PHP. Additionally, you may pass fully qualified class or interface names. - -If you pass an invalid option now, an -:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` -is thrown:: +This would add an option - ``username`` - and give it a default value of +``root``. If the user passes in a ``username`` option, that value will +override this default. You don't need to configure ``username`` as an optional +option. - $mailer = new Mailer(array( - 'host' => 25, - )); - - // InvalidOptionsException: The option "host" with value "25" is - // expected to be of type "string" - -In sub-classes, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes` -to add additional allowed types without erasing the ones already set. - -Value Validation +Required Options ~~~~~~~~~~~~~~~~ -Some options can only take one of a fixed list of predefined values. For -example, suppose the ``Mailer`` class has a ``transport`` option which can be -one of ``sendmail``, ``mail`` and ``smtp``. Use the method -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues` -to verify that the passed option contains one of these values:: +The ``host`` option is required: the class can't work without it. You can set +the required options by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setRequired`:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { - // ... - - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setDefault('transport', 'sendmail'); - $resolver->setAllowedValues('transport', array('sendmail', 'mail', 'smtp')); - } + $resolver->setRequired(array('host')); } -If you pass an invalid transport, an -:class:`Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException` -is thrown:: +You are now able to use the class without errors:: $mailer = new Mailer(array( - 'transport' => 'send-mail', + 'host' => 'smtp.example.org', )); - // InvalidOptionsException: The option "transport" has the value - // "send-mail", but is expected to be one of "sendmail", "mail", "smtp" - -For options with more complicated validation schemes, pass a closure which -returns ``true`` for acceptable values and ``false`` for invalid values:: + echo $mailer->getHost(); // 'smtp.example.org' - $resolver->setAllowedValues(array( - // ... - $resolver->setAllowedValues('transport', function ($value) { - // return true or false - }); - )); +If you don't pass a required option, a +:class:`Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException` +will be thrown. -In sub-classes, you can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedValues` -to add additional allowed values without erasing the ones already set. +.. tip:: -Option Normalization -~~~~~~~~~~~~~~~~~~~~ + To determine if an option is required, you can use the + :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isRequired` + method. -Sometimes, option values need to be normalized before you can use them. For -instance, assume that the ``host`` should always start with ``http://``. To do -that, you can write normalizers. Normalizers are executed after validating an -option. You can configure a normalizer by calling -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setNormalizer`:: +Optional Options +~~~~~~~~~~~~~~~~ - use Symfony\Component\OptionsResolver\Options; +Sometimes, an option can be optional (e.g. the ``password`` option in the +``Mailer`` class), but it doesn't have a default value. You can configure +these options by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setOptional`:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - - $resolver->setNormalizer('host', function (Options $options, $value) { - if ('http://' !== substr($value, 0, 7)) { - $value = 'http://'.$value; - } - - return $value; - }); - } + $resolver->setOptional(array('password')); } -The normalizer receives the actual ``$value`` and returns the normalized form. -You see that the closure also takes an ``$options`` parameter. This is useful -if you need to use other options during normalization:: +Options with defaults are already marked as optional. - // ... - class Mailer - { - // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setNormalizer('host', function (Options $options, $value) { - if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { - if ('ssl' === $options['encryption']) { - $value = 'https://'.$value; - } else { - $value = 'http://'.$value; - } - } +.. tip:: - return $value; - }); - } - } + When setting an option as optional, you can't be sure if it's in the array + or not. You have to check if the option exists before using it. + + To avoid checking if it exists everytime, you can also set a default of + ``null`` to an option using the ``setDefaults()`` method (see `Set Default Values`_), + this means the element always exists in the array, but with a default of + ``null``. Default Values that Depend on another Option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suppose you want to set the default value of the ``port`` option based on the -encryption chosen by the user of the ``Mailer`` class. More precisely, you want -to set the port to ``465`` if SSL is used and to ``25`` otherwise. - -You can implement this feature by passing a closure as the default value of -the ``port`` option. The closure receives the options as argument. Based on -these options, you can return the desired default value:: +Suppose you add a ``port`` option to the ``Mailer`` class, whose default +value you guess based on the encryption. You can do that easily by using a +closure as the default value:: use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setDefault('encryption', null); - $resolver->setDefault('port', function (Options $options) { + $resolver->setDefaults(array( + 'encryption' => null, + 'port' => function (Options $options) { if ('ssl' === $options['encryption']) { return 465; } return 25; - }); - } + }, + )); } +The :class:`Symfony\\Component\\OptionsResolver\\Options` class implements +:phpclass:`ArrayAccess`, :phpclass:`Iterator` and :phpclass:`Countable`. That +means you can handle it just like a normal array containing the options. + .. caution:: - The argument of the callable must be type hinted as ``Options``. Otherwise, - the callable itself is considered as the default value of the option. + The first argument of the closure must be typehinted as ``Options``, + otherwise it is considered as the value. -.. note:: +Overwriting default Values +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A previously set default value can be overwritten by invoking +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefaults` +again. When using a closure as the new value it is passed 2 arguments: - The closure is only executed if the ``port`` option isn't set by the user - or overwritten in a sub-class. +* ``$options``: an :class:`Symfony\\Component\\OptionsResolver\\Options` + instance with all the other default options +* ``$previousValue``: the previous set default value + +.. code-block:: php -A previously set default value can be accessed by adding a second argument to -the closure:: + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setDefaults(array( - 'encryption' => null, - 'host' => 'example.org', - )); - } - } + $resolver->setDefaults(array( + 'encryption' => 'ssl', + 'host' => 'localhost', + )); - class GoogleMailer extends Mailer - { - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - $options->setDefault('host', function (Options $options, $previousValue) { - if ('ssl' === $options['encryption']) { - return 'secure.example.org' - } - - // Take default value configured in the base class - return $previousValue; - }); - } + // ... + $resolver->setDefaults(array( + 'encryption' => 'tls', // simple overwrite + 'host' => function (Options $options, $previousValue) { + return 'localhost' == $previousValue + ? '127.0.0.1' + : $previousValue; + }, + )); } -As seen in the example, this feature is mostly useful if you want to reuse the -default values set in parent classes in sub-classes. +.. tip:: -Options without Default Values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If the previous default value is calculated by an expensive closure and + you don't need access to it, you can use the + :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::replaceDefaults` + method instead. It acts like ``setDefaults`` but simply erases the + previous value to improve performance. This means that the previous + default value is not available when overwriting with another closure:: -In some cases, it is useful to define an option without setting a default value. -This is useful if you need to know whether or not the user *actually* set -an option or not. For example, if you set the default value for an option, -it's not possible to know whether the user passed this value or if it simply -comes from the default:: + use Symfony\Component\OptionsResolver\Options; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; - // ... - class Mailer - { // ... - public function configureOptions(OptionsResolver $resolver) + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - $resolver->setDefault('port', 25); - } - - // ... - public function sendMail($from, $to) - { - // Is this the default value or did the caller of the class really - // set the port to 25? - if (25 === $this->options['port']) { - // ... - } - } - } + $resolver->setDefaults(array( + 'encryption' => 'ssl', + 'heavy' => function (Options $options) { + // Some heavy calculations to create the $result -You can use :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setDefined` -to define an option without setting a default value. Then the option will only -be included in the resolved options if it was actually passed to -:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::resolve`:: + return $result; + }, + )); - // ... - class Mailer - { - // ... + $resolver->replaceDefaults(array( + 'encryption' => 'tls', // simple overwrite + 'heavy' => function (Options $options) { + // $previousValue not available + // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setDefined('port'); + return $someOtherResult; + }, + )); } - // ... - public function sendMail($from, $to) - { - if (array_key_exists('port', $this->options)) { - echo 'Set!'; - } else { - echo 'Not Set!'; - } - } - } +.. note:: - $mailer = new Mailer(); - $mailer->sendMail($from, $to); - // => Not Set! + Existing option keys that you do not mention when overwriting are preserved. - $mailer = new Mailer(array( - 'port' => 25, - )); - $mailer->sendMail($from, $to); - // => Set! +Configure Allowed Values +~~~~~~~~~~~~~~~~~~~~~~~~ -You can also pass an array of option names if you want to define multiple -options in one go:: +Not all values are valid values for options. Suppose the ``Mailer`` class has +a ``transport`` option, it can only be one of ``sendmail``, ``mail`` or +``smtp``. You can configure these allowed values by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedValues`:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - // ... - $resolver->setDefined(array('port', 'encryption')); - } + + $resolver->setAllowedValues(array( + 'encryption' => array(null, 'ssl', 'tls'), + )); } -The methods :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::isDefined` -and :method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::getDefinedOptions` -let you find out which options are defined:: +There is also an +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedValues` +method, which you can use if you want to add an allowed value to the previously +configured allowed values. + +Configure Allowed Types +~~~~~~~~~~~~~~~~~~~~~~~ + +You can also specify allowed types. For instance, the ``port`` option can +be anything, but it must be an integer. You can configure these types by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setAllowedTypes`:: // ... - class GoogleMailer extends Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { // ... - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - if ($resolver->isDefined('host')) { - // One of the following was called: + $resolver->setAllowedTypes(array( + 'port' => 'integer', + )); + } - // $resolver->setDefault('host', ...); - // $resolver->setRequired('host'); - // $resolver->setDefined('host'); - } +Possible types are the ones associated with the ``is_*`` PHP functions or a +class name. You can also pass an array of types as the value. For instance, +``array('null', 'string')`` allows ``port`` to be ``null`` or a ``string``. - $definedOptions = $resolver->getDefinedOptions(); - } - } +There is also an +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::addAllowedTypes` +method, which you can use to add an allowed type to the previous allowed types. -Performance Tweaks -~~~~~~~~~~~~~~~~~~ +Normalize the Options +~~~~~~~~~~~~~~~~~~~~~ -With the current implementation, the ``configureOptions()`` method will be -called for every single instance of the ``Mailer`` class. Depending on the -amount of option configuration and the number of created instances, this may add -noticeable overhead to your application. If that overhead becomes a problem, you -can change your code to do the configuration only once per class:: +Some values need to be normalized before you can use them. For instance, +pretend that the ``host`` should always start with ``http://``. To do that, +you can write normalizers. These closures will be executed after all options +are passed and should return the normalized value. You can configure these +normalizers by calling +:method:`Symfony\\Component\\OptionsResolver\\OptionsResolver::setNormalizers`:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { - private static $resolversByClass = array(); - - protected $options; - - public function __construct(array $options = array()) - { - // What type of Mailer is this, a Mailer, a GoogleMailer, ... ? - $class = get_class($this); - - // Was configureOptions() executed before for this class? - if (!isset(self::$resolversByClass[$class])) { - self::$resolversByClass[$class] = new OptionsResolver(); - $this->configureOptions(self::$resolversByClass[$class]); - } + // ... - $this->options = self::$resolversByClass[$class]->resolve($options); - } + $resolver->setNormalizers(array( + 'host' => function (Options $options, $value) { + if ('http://' !== substr($value, 0, 7)) { + $value = 'http://'.$value; + } - public function configureOptions(OptionsResolver $resolver) - { - // ... - } + return $value; + }, + )); } -Now the :class:`Symfony\\Component\\OptionsResolver\\OptionsResolver` instance -will be created once per class and reused from that on. Be aware that this may -lead to memory leaks in long-running applications, if the default options contain -references to objects or object graphs. If that's the case for you, implement a -method ``clearOptionsConfig()`` and call it periodically:: +You see that the closure also gets an ``$options`` parameter. Sometimes, you +need to use the other options for normalizing:: // ... - class Mailer + protected function setDefaultOptions(OptionsResolverInterface $resolver) { - private static $resolversByClass = array(); + // ... - public static function clearOptionsConfig() - { - self::$resolversByClass = array(); - } + $resolver->setNormalizers(array( + 'host' => function (Options $options, $value) { + if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) { + if ($options['ssl']) { + $value = 'https://'.$value; + } else { + $value = 'http://'.$value; + } + } - // ... + return $value; + }, + )); } -That's it! You now have all the tools and knowledge needed to easily process -options in your code. - .. _Packagist: https://packagist.org/packages/symfony/options-resolver -.. _Form component: http://symfony.com/doc/current/components/form/introduction.html -.. _CHANGELOG: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/OptionsResolver/CHANGELOG.md#260 diff --git a/components/phpunit_bridge.rst b/components/phpunit_bridge.rst deleted file mode 100644 index ae5e7b4da33..00000000000 --- a/components/phpunit_bridge.rst +++ /dev/null @@ -1,246 +0,0 @@ -.. index:: - single: PHPUnitBridge - single: Components; PHPUnitBridge - -The PHPUnit Bridge -================== - - The PHPUnit Bridge provides utilities to report legacy tests and usage of - deprecated code and a helper for time-sensitive tests. - -It comes with the following features: - -* Forces the tests to use a consistent locale (``C``); - -* Auto-register ``class_exists`` to load Doctrine annotations (when used); - -* It displays the whole list of deprecated features used in the application; - -* Displays the stack trace of a deprecation on-demand; - -* Provides a ``ClockMock`` helper class for time-sensitive tests. - -.. versionadded:: 2.7 - The PHPUnit Bridge was introduced in Symfony 2.7. It is however possible to - install the bridge in any Symfony application (even 2.3). - -Installation ------------- - -You can install the component in 2 different ways: - -* :doc:`Install it via Composer ` - (``symfony/phpunit-bridge`` on `Packagist`_); as a dev dependency; - -* Use the official Git repository (https://github.com/symfony/phpunit-bridge). - -.. include:: /components/require_autoload.rst.inc - -Usage ------ - -Once the component installed, it automatically registers a -`PHPUnit event listener`_ which in turn registers a `PHP error handler`_ -called :class:`Symfony\\Bridge\\PhpUnit\\DeprecationErrorHandler`. After -running your PHPUnit tests, you will get a report similar to this one: - -.. image:: /images/components/phpunit_bridge/report.png - -The summary includes: - -**Unsilenced** - Reports deprecation notices that were triggered without the recommended - `@-silencing operator`_. - -**Legacy** - Deprecation notices denote tests that explicitly test some legacy features. - -**Remaining/Other** - Deprecation notices are all other (non-legacy) notices, grouped by message, - test class and method. - -Trigger Deprecation Notices ---------------------------- - -Deprecation notices can be triggered by using:: - - @trigger_error('Your deprecation message', E_USER_DEPRECATED); - -Without the `@-silencing operator`_, users would need to opt-out from deprecation -notices. Silencing by default swaps this behavior and allows users to opt-in -when they are ready to cope with them (by adding a custom error handler like the -one provided by this bridge). When not silenced, deprecation notices will appear -in the **Unsilenced** section of the deprecation report. - -Mark Tests as Legacy --------------------- - -There are four ways to mark a test as legacy: - -* (**Recommended**) Add the ``@group legacy`` annotation to its class or method; - -* Make its class name start with the ``Legacy`` prefix; - -* Make its method name start with ``testLegacy`` instead of ``test``; - -* Make its data provider start with ``provideLegacy`` or ``getLegacy``. - -Configuration -------------- - -In case you need to inspect the stack trace of a particular deprecation -triggered by your unit tests, you can set the ``SYMFONY_DEPRECATIONS_HELPER`` -`environment variable`_ to a regular expression that matches this deprecation's -message, enclosed with ``/``. For example, with: - -.. code-block:: xml - - - - - - - - - - - - -PHPUnit_ will stop your test suite once a deprecation notice is triggered whose -message contains the ``"foobar"`` string. - -Making Tests Fail ------------------ - -By default, any non-legacy-tagged or any non-`@-silenced`_ deprecation notices will -make tests fail. Alternatively, setting ``SYMFONY_DEPRECATIONS_HELPER`` to an -arbitrary value (ex: ``320``) will make the tests fails only if a higher number -of deprecation notices is reached (``0`` is the default value). You can also set -the value ``"weak"`` which will make the bridge ignore any deprecation notices. -This is useful to projects that must use deprecated interfaces for backward -compatibility reasons. - -Time-sensitive Tests --------------------- - -Use Case -~~~~~~~~ - -If you have this kind of time-related tests:: - - use Symfony\Component\Stopwatch\Stopwatch; - - class MyTest extends \PHPUnit_Framework_TestCase - { - public function testSomething() - { - $stopwatch = new Stopwatch(); - - $stopwatch->start(); - sleep(10); - $duration = $stopwatch->stop(); - - $this->assertEquals(10, $duration); - } - } - -You used the :doc:`Symfony Stopwatch Component ` to -calculate the duration time of your process, here 10 seconds. However, depending -on the load of the server your the processes running on your local machine, the -``$duration`` could for example be `10.000023s` instead of `10s`. - -This kind of tests are called transient tests: they are failing randomly -depending on spurious and external circumstances. They are often cause trouble -when using public continuous integration services like `Travis CI`_. - -Clock Mocking -~~~~~~~~~~~~~ - -The :class:`Symfony\\Bridge\\PhpUnit\\ClockMock` class provided by this bridge -allows you to mock the PHP's built-in time functions ``time()``, -``microtime()``, ``sleep()`` and ``usleep()``. - -To use the ``ClockMock`` class in your test, you can: - -* (**Recommended**) Add the ``@group time-sensitive`` annotation to its class or - method; - -* Register it manually by calling ``ClockMock::register(__CLASS__)`` and - ``ClockMock::withClockMock(true)`` before the test and - ``ClockMock::withClockMock(false)`` after the test. - -As a result, the following is guarenteed to work and is no longer a transient -test:: - - use Symfony\Component\Stopwatch\Stopwatch; - - /** - * @group time-sensitive - */ - class MyTest extends \PHPUnit_Framework_TestCase - { - public function testSomething() - { - $stopwatch = new Stopwatch(); - - $stopwatch->start(); - sleep(10); - $duration = $stopwatch->stop(); - - $this->assertEquals(10, $duration); - } - } - -And that's all! - -.. tip:: - - An added bonus of using the ``ClockMock`` class is that time passes - instantly. Using PHP's ``sleep(10)`` will make your test wait for 10 - actual seconds (more or less). In contrast, the ``ClockMock`` class - advances the internal clock the given number of seconds without actually - waiting that time, so your test will execute 10 seconds faster. - -Troubleshooting -~~~~~~~~~~~~~~~ - -The ``@group time-sensitive`` works "by convention" and assumes that the -namespace of the tested class can be obtained just by removing the ``\Tests\`` -part from the test namespace. I.e. that if the your test case fully-qualified -class name (FQCN) is ``App\Tests\Watch\DummyWatchTest``, it assumes the tested -class FQCN is ``App\Watch\DummyWatch``. - -If this convention doesn't work for your application, you can also configure -the mocked namespaces in the ``phpunit.xml`` file, as done for example in the -:doc:`HttpKernel Component `: - -.. code-block:: xml - - - - - - - - - - - Symfony\Component\HttpFoundation - - - - - - -.. _PHPUnit: https://phpunit.de -.. _`PHPUnit event listener`: https://phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener -.. _`PHP error handler`: http://php.net/manual/en/book.errorfunc.php -.. _`environment variable`: https://phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables -.. _Packagist: https://packagist.org/packages/symfony/phpunit-bridge -.. _`@-silencing operator`: http://php.net/manual/en/language.operators.errorcontrol.php -.. _`@-silenced`: http://php.net/manual/en/language.operators.errorcontrol.php -.. _`Travis CI`: https://travis-ci.com/ diff --git a/components/process.rst b/components/process.rst index aaa732d053c..c848fcc07bc 100644 --- a/components/process.rst +++ b/components/process.rst @@ -24,50 +24,30 @@ The :class:`Symfony\\Component\\Process\\Process` class allows you to execute a command in a sub-process:: use Symfony\Component\Process\Process; - use Symfony\Component\Process\Exception\ProcessFailedException; $process = new Process('ls -lsa'); $process->run(); // executes after the command finishes if (!$process->isSuccessful()) { - throw new ProcessFailedException($process); + throw new \RuntimeException($process->getErrorOutput()); } - echo $process->getOutput(); + print $process->getOutput(); The component takes care of the subtle differences between the different platforms when executing the command. +.. versionadded:: 2.2 + The ``getIncrementalOutput()`` and ``getIncrementalErrorOutput()`` methods + were introduced in Symfony 2.2. + The ``getOutput()`` method always returns the whole content of the standard output of the command and ``getErrorOutput()`` the content of the error output. Alternatively, the :method:`Symfony\\Component\\Process\\Process::getIncrementalOutput` and :method:`Symfony\\Component\\Process\\Process::getIncrementalErrorOutput` methods returns the new outputs since the last call. -The :method:`Symfony\\Component\\Process\\Process::clearOutput` method clears -the contents of the output and -:method:`Symfony\\Component\\Process\\Process::clearErrorOutput` clears -the contents of the error output. - -The ``mustRun()`` method is identical to ``run()``, except that it will throw -a :class:`Symfony\\Component\\Process\\Exception\\ProcessFailedException` -if the process couldn't be executed successfully (i.e. the process exited -with a non-zero code):: - - use Symfony\Component\Process\Exception\ProcessFailedException; - use Symfony\Component\Process\Process; - - $process = new Process('ls -lsa'); - - try { - $process->mustRun(); - - echo $process->getOutput(); - } catch (ProcessFailedException $e) { - echo $e->getMessage(); - } - Getting real-time Process Output -------------------------------- @@ -87,6 +67,9 @@ anonymous function to the } }); +.. versionadded:: 2.1 + The non-blocking feature was introduced in 2.1. + Running Processes Asynchronously -------------------------------- @@ -131,6 +114,9 @@ are done doing other stuff:: Stopping a Process ------------------ +.. versionadded:: 2.3 + The ``signal`` parameter of the ``stop`` method was introduced in Symfony 2.3. + Any asynchronous process can be stopped at any time with the :method:`Symfony\\Component\\Process\\Process::stop` method. This method takes two arguments: a timeout and a signal. Once the timeout is reached, the signal @@ -167,6 +153,10 @@ To make your code work better on all platforms, you might want to use the $builder = new ProcessBuilder(array('ls', '-lsa')); $builder->getProcess()->run(); +.. versionadded:: 2.3 + The :method:`ProcessBuilder::setPrefix` + method was introduced in Symfony 2.3. + In case you are building a binary driver, you can use the :method:`Symfony\\Component\\Process\\ProcessBuilder::setPrefix` method to prefix all the generated process commands. @@ -223,25 +213,12 @@ check regularly:: .. _reference-process-signal: -Process Idle Timeout --------------------- - -In contrast to the timeout of the previous paragraph, the idle timeout only -considers the time since the last output was produced by the process:: - - use Symfony\Component\Process\Process; - - $process = new Process('something-with-variable-runtime'); - $process->setTimeout(3600); - $process->setIdleTimeout(60); - $process->run(); - -In the case above, a process is considered timed out, when either the total runtime -exceeds 3600 seconds, or the process does not produce any output for 60 seconds. - Process Signals --------------- +.. versionadded:: 2.3 + The ``signal`` method was introduced in Symfony 2.3. + When running a program asynchronously, you can send it POSIX signals with the :method:`Symfony\\Component\\Process\\Process::signal` method:: @@ -265,6 +242,9 @@ When running a program asynchronously, you can send it POSIX signals with the Process Pid ----------- +.. versionadded:: 2.3 + The ``getPid`` method was introduced in Symfony 2.3. + You can access the `pid`_ of a running process with the :method:`Symfony\\Component\\Process\\Process::getPid` method. @@ -283,29 +263,6 @@ You can access the `pid`_ of a running process with the you may have to prefix your commands with `exec`_. Please read `Symfony Issue#5759`_ to understand why this is happening. -Disabling Output ----------------- - -As standard output and error output are always fetched from the underlying process, -it might be convenient to disable output in some cases to save memory. -Use :method:`Symfony\\Component\\Process\\Process::disableOutput` and -:method:`Symfony\\Component\\Process\\Process::enableOutput` to toggle this feature:: - - use Symfony\Component\Process\Process; - - $process = new Process('/usr/bin/php worker.php'); - $process->disableOutput(); - $process->run(); - -.. caution:: - - You can not enable or disable the output while the process is running. - - If you disable the output, you cannot access ``getOutput``, - ``getIncrementalOutput``, ``getErrorOutput`` or ``getIncrementalErrorOutput``. - Moreover, you could not pass a callback to the ``start``, ``run`` or ``mustRun`` - methods or use ``setIdleTimeout``. - .. _`Symfony Issue#5759`: https://github.com/symfony/symfony/issues/5759 .. _`PHP Bug#39992`: https://bugs.php.net/bug.php?id=39992 .. _`exec`: https://en.wikipedia.org/wiki/Exec_(operating_system) diff --git a/components/property_access/introduction.rst b/components/property_access/introduction.rst index 041f7543b89..ae8e6a66e4f 100644 --- a/components/property_access/introduction.rst +++ b/components/property_access/introduction.rst @@ -8,6 +8,10 @@ The PropertyAccess Component The PropertyAccess component provides function to read and write from/to an object or array using a simple string notation. +.. versionadded:: 2.2 + The PropertyAccess component was introduced in Symfony 2.2. Previously, + the ``PropertyPath`` class was located in the Form component. + Installation ------------ @@ -31,6 +35,10 @@ default configuration:: $accessor = PropertyAccess::createPropertyAccessor(); +.. versionadded:: 2.3 + The :method:`Symfony\\Component\\PropertyAccess\\PropertyAccess::createPropertyAccessor` + method was introduced in Symfony 2.3. Previously, it was called ``getPropertyAccessor()``. + Reading from Arrays ------------------- @@ -173,8 +181,6 @@ The ``getValue`` method can also use the magic ``__get`` method:: var_dump($accessor->getValue($person, 'Wouter')); // array(...) -.. _components-property-access-magic-call: - Magic ``__call()`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -211,6 +217,9 @@ enable this feature by using :class:`Symfony\\Component\\PropertyAccess\\Propert var_dump($accessor->getValue($person, 'wouter')); // array(...) +.. versionadded:: 2.3 + The use of magic ``__call()`` method was introduced in Symfony 2.3. + .. caution:: The ``__call`` feature is disabled by default, you can enable it by calling @@ -306,32 +315,6 @@ see `Enable other Features`_. var_dump($person->getWouter()); // array(...) -Checking Property Paths ------------------------ - -When you want to check whether -:method:`PropertyAccessor::getValue` -can safely be called without actually calling that method, you can use -:method:`PropertyAccessor::isReadable` -instead:: - - $person = new Person(); - - if ($accessor->isReadable($person, 'firstName')) { - // ... - } - -The same is possible for :method:`PropertyAccessor::setValue`: -Call the -:method:`PropertyAccessor::isWritable` -method to find out whether a property path can be updated:: - - $person = new Person(); - - if ($accessor->isWritable($person, 'firstName')) { - // ... - } - Mixing Objects and Arrays ------------------------- diff --git a/components/routing/hostname_pattern.rst b/components/routing/hostname_pattern.rst index 4c49199fcaa..0b2f5392be6 100644 --- a/components/routing/hostname_pattern.rst +++ b/components/routing/hostname_pattern.rst @@ -4,6 +4,9 @@ How to Match a Route Based on the Host ====================================== +.. versionadded:: 2.2 + Host matching support was introduced in Symfony 2.2 + You can also match on the HTTP *host* of the incoming request. .. configuration-block:: diff --git a/components/routing/introduction.rst b/components/routing/introduction.rst index 350585e0547..409ed76b19a 100644 --- a/components/routing/introduction.rst +++ b/components/routing/introduction.rst @@ -98,6 +98,9 @@ A full route definition can contain up to seven parts: #. An array of methods. These enforce a certain HTTP request method (``HEAD``, ``GET``, ``POST``, ...). +.. versionadded:: 2.2 + Host matching support was introduced in Symfony 2.2 + Take the following route, which combines several of these ideas:: $route = new Route( @@ -167,6 +170,7 @@ host to all routes of a subtree using methods provided by the $rootCollection->addCollection($subCollection); + Set the Request Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/components/security/authentication.rst b/components/security/authentication.rst index 06fdc8faaeb..35aed4fe69a 100644 --- a/components/security/authentication.rst +++ b/components/security/authentication.rst @@ -10,11 +10,10 @@ firewall map is able to extract the user's credentials from the current a token, containing these credentials. The next thing the listener should do is ask the authentication manager to validate the given token, and return an *authenticated* token if the supplied credentials were found to be valid. -The listener should then store the authenticated token using -:class:`the token storage `:: +The listener should then store the authenticated token in the security context:: use Symfony\Component\Security\Http\Firewall\ListenerInterface; - use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; + use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; @@ -22,9 +21,9 @@ The listener should then store the authenticated token using class SomeAuthenticationListener implements ListenerInterface { /** - * @var TokenStorageInterface + * @var SecurityContextInterface */ - private $tokenStorage; + private $securityContext; /** * @var AuthenticationManagerInterface @@ -55,7 +54,7 @@ The listener should then store the authenticated token using ->authenticationManager ->authenticate($unauthenticatedToken); - $this->tokenStorage->setToken($authenticatedToken); + $this->securityContext->setToken($authenticatedToken); } } diff --git a/components/security/authorization.rst b/components/security/authorization.rst index 5f5287bd64c..2ca0e768e8b 100644 --- a/components/security/authorization.rst +++ b/components/security/authorization.rst @@ -7,8 +7,8 @@ Authorization When any of the authentication providers (see :ref:`authentication_providers`) has verified the still-unauthenticated token, an authenticated token will be returned. The authentication listener should set this token directly -in the :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface` -using its :method:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\Storage\\TokenStorageInterface::setToken` +in the :class:`Symfony\\Component\\Security\\Core\\SecurityContextInterface` +using its :method:`Symfony\\Component\\Security\\Core\\SecurityContextInterface::setToken` method. From then on, the user is authenticated, i.e. identified. Now, other parts @@ -85,6 +85,13 @@ of :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterf which means they have to implement a few methods which allows the decision manager to use them: +``supportsAttribute($attribute)`` + will be used to check if the voter knows how to handle the given attribute; + +``supportsClass($class)`` + will be used to check if the voter is able to grant or deny access for + an object of the given class; + ``vote(TokenInterface $token, $object, array $attributes)`` this method will do the actual voting and return a value equal to one of the class constants of :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`, @@ -220,25 +227,24 @@ are required for the current user to get access to the application:: $authenticationManager ); -Authorization Checker -~~~~~~~~~~~~~~~~~~~~~ +Security Context +~~~~~~~~~~~~~~~~ The access decision manager is also available to other parts of the application -via the :method:`Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker::isGranted` -method of the :class:`Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationChecker`. +via the :method:`Symfony\\Component\\Security\\Core\\SecurityContext::isGranted` +method of the :class:`Symfony\\Component\\Security\\Core\\SecurityContext`. A call to this method will directly delegate the question to the access decision manager:: - use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; + use Symfony\Component\Security\SecurityContext; use Symfony\Component\Security\Core\Exception\AccessDeniedException; - $authorizationChecker = new AuthorizationChecker( - $tokenStorage, + $securityContext = new SecurityContext( $authenticationManager, $accessDecisionManager ); - if (!$authorizationChecker->isGranted('ROLE_ADMIN')) { + if (!$securityContext->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } diff --git a/components/security/firewall.rst b/components/security/firewall.rst index c3fe82f4c49..8d30debff6e 100644 --- a/components/security/firewall.rst +++ b/components/security/firewall.rst @@ -1,36 +1,32 @@ .. index:: single: Security, Firewall -The Firewall and Authorization -============================== +The Firewall and Security Context +================================= -Central to the Security component is authorization. This is handled by an instance -of :class:`Symfony\\Component\\Security\\Core\\Authorization\\AuthorizationCheckerInterface`. -When all steps in the process of authenticating the user have been taken successfully, -you can ask the authorization checker if the authenticated user has access to a +Central to the Security component is the security context, which is an instance +of :class:`Symfony\\Component\\Security\\Core\\SecurityContextInterface`. When all +steps in the process of authenticating the user have been taken successfully, +you can ask the security context if the authenticated user has access to a certain action or resource of the application:: - use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; + use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Core\Exception\AccessDeniedException; - // instance of Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface - $tokenStorage = ...; - // instance of Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface $authenticationManager = ...; // instance of Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface $accessDecisionManager = ...; - $authorizationChecker = new AuthorizationChecker( - $tokenStorage, + $securityContext = new SecurityContext( $authenticationManager, $accessDecisionManager ); // ... authenticate the user - if (!$authorizationChecker->isGranted('ROLE_ADMIN')) { + if (!$securityContext->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } @@ -119,7 +115,7 @@ which will eventually result in an "HTTP/1.1 403: Access Denied" response. Entry Points ~~~~~~~~~~~~ -When the user is not authenticated at all (i.e. when the token storage +When the user is not authenticated at all (i.e. when the security context has no token yet), the firewall's entry point will be called to "start" the authentication process. An entry point should implement :class:`Symfony\\Component\\Security\\Http\\EntryPoint\\AuthenticationEntryPointInterface`, diff --git a/components/security/introduction.rst b/components/security/introduction.rst index 57957f6516a..96ac494470b 100644 --- a/components/security/introduction.rst +++ b/components/security/introduction.rst @@ -21,23 +21,6 @@ You can install the component in 2 different ways: .. include:: /components/require_autoload.rst.inc -The Security component is divided into four smaller sub-components which can be -used separately: - -``symfony/security-core`` - It provides all the common security features, from authentication to - authorization and from encoding passwords to loading users. - -``symfony/security-http`` - It integrates the core sub-component with the HTTP protocol to handle HTTP - requests and responses. - -``symfony/security-csrf`` - It provides protection against `CSRF attacks`_. - -``symfony/security-acl`` - It provides a fine grained permissions mechanism based on Access Control Lists. - Sections -------- @@ -47,4 +30,3 @@ Sections * :doc:`/components/security/secure_tools` .. _Packagist: https://packagist.org/packages/symfony/security -.. _`CSRF attacks`: https://en.wikipedia.org/wiki/Cross-site_request_forgery diff --git a/components/security/secure_tools.rst b/components/security/secure_tools.rst index 16a2c5256f8..a7060c26597 100644 --- a/components/security/secure_tools.rst +++ b/components/security/secure_tools.rst @@ -1,5 +1,5 @@ -Securely Generating Random Values -================================= +Securely Comparing Strings and Generating Random Values +======================================================= The Symfony Security component comes with a collection of nice utilities related to security. These utilities are used by Symfony, but you should diff --git a/components/serializer.rst b/components/serializer.rst index be53706a54e..9d1d80df053 100644 --- a/components/serializer.rst +++ b/components/serializer.rst @@ -33,12 +33,8 @@ You can install the component in 2 different ways: * :doc:`Install it via Composer ` (``symfony/serializer`` on `Packagist`_); * Use the official Git repository (https://github.com/symfony/serializer). - .. include:: /components/require_autoload.rst.inc -To use the ``ObjectNormalizer``, the :doc:`PropertyAccess component ` -must also be installed. - Usage ----- @@ -49,19 +45,13 @@ which Encoders and Normalizer are going to be available:: use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Encoder\JsonEncoder; - use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; + use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; $encoders = array(new XmlEncoder(), new JsonEncoder()); - $normalizers = array(new ObjectNormalizer()); + $normalizers = array(new GetSetMethodNormalizer()); $serializer = new Serializer($normalizers, $encoders); -The preferred normalizer is the -:class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`, but other -normalizers are available. -To read more about them, refer to the `Normalizers`_ section of this page. All -the examples shown below use the ``ObjectNormalizer``. - Serializing an Object --------------------- @@ -74,7 +64,6 @@ exists in your project:: { private $age; private $name; - private $sportsman; // Getters public function getName() @@ -87,12 +76,6 @@ exists in your project:: return $this->age; } - // Issers - public function isSportsman() - { - return $this->sportsman; - } - // Setters public function setName($name) { @@ -103,11 +86,6 @@ exists in your project:: { $this->age = $age; } - - public function setSportsman($sportsman) - { - $this->sportsman = $sportsman; - } } Now, if you want to serialize this object into JSON, you only need to @@ -116,11 +94,10 @@ use the Serializer service created before:: $person = new Acme\Person(); $person->setName('foo'); $person->setAge(99); - $person->setSportsman(false); $jsonContent = $serializer->serialize($person, 'json'); - // $jsonContent contains {"name":"foo","age":99,"sportsman":false} + // $jsonContent contains {"name":"foo","age":99} echo $jsonContent; // or return it in a Response @@ -128,6 +105,29 @@ The first parameter of the :method:`Symfony\\Component\\Serializer\\Serializer:: is the object to be serialized and the second is used to choose the proper encoder, in this case :class:`Symfony\\Component\\Serializer\\Encoder\\JsonEncoder`. +Ignoring Attributes when Serializing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.3 + The :method:`GetSetMethodNormalizer::setIgnoredAttributes` + method was introduced in Symfony 2.3. + +As an option, there's a way to ignore attributes from the origin object when +serializing. To remove those attributes use the +:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setIgnoredAttributes` +method on the normalizer definition:: + + use Symfony\Component\Serializer\Serializer; + use Symfony\Component\Serializer\Encoder\JsonEncoder; + use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; + + $normalizer = new GetSetMethodNormalizer(); + $normalizer->setIgnoredAttributes(array('age')); + $encoder = new JsonEncoder(); + + $serializer = new Serializer(array($normalizer), array($encoder)); + $serializer->serialize($person, 'json'); // Output: {"name":"foo"} + Deserializing an Object ----------------------- @@ -138,7 +138,6 @@ of the ``Person`` class would be encoded in XML format:: foo 99 - false EOF; @@ -151,301 +150,38 @@ needs three parameters: #. The name of the class this information will be decoded to #. The encoder used to convert that information into an array -Deserializing in an Existing Object -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The serializer can also be used to update an existing object:: +Using Camelized Method Names for Underscored Attributes +------------------------------------------------------- - $person = new Acme\Person(); - $person->setName('bar'); - $person->setAge(99); - $person->setSportsman(true); - - $data = << - foo - 69 - - EOF; - - $serializer->deserialize($data, 'Acme\Person', 'xml', array('object_to_populate' => $person)); - // $obj2 = Acme\Person(name: 'foo', age: '99', sportsman: true) - -This is a common need when working with an ORM. - -.. _component-serializer-attributes-groups: - -Attributes Groups ------------------ - -Sometimes, you want to serialize different sets of attributes from your -entities. Groups are a handy way to achieve this need. - -Assume you have the following plain-old-PHP object:: - - namespace Acme; - - class MyObj - { - public $foo; - - private $bar; - - public function getBar() - { - return $this->bar; - } - - public function setBar($bar) - { - return $this->bar = $bar; - } - } +.. versionadded:: 2.3 + The :method:`GetSetMethodNormalizer::setCamelizedAttributes` + method was introduced in Symfony 2.3. -The definition of serialization can be specified using annotations, XML -or YAML. The :class:`Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory` -that will be used by the normalizer must be aware of the format to use. - -Initialize the :class:`Symfony\\Component\\Serializer\\Mapping\\Factory\\ClassMetadataFactory` -like the following:: - - use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; - // For annotations - use Doctrine\Common\Annotations\AnnotationReader; - use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; - // For XML - // use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; - // For YAML - // use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; - - $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); - // For XML - // $classMetadataFactory = new ClassMetadataFactory(new XmlFileLoader('/path/to/your/definition.xml')); - // For YAML - // $classMetadataFactory = new ClassMetadataFactory(new YamlFileLoader('/path/to/your/definition.yml')); - -.. _component-serializer-attributes-groups-annotations: - -Then, create your groups definition: - -.. configuration-block:: - - .. code-block:: php-annotations - - namespace Acme; - - use Symfony\Component\Serializer\Annotation\Groups; - - class MyObj - { - /** - * @Groups({"group1", "group2"}) - */ - public $foo; - - /** - * @Groups({"group3"}) - */ - public function getBar() // is* methods are also supported - { - return $this->bar; - } - - // ... - } - - .. code-block:: yaml - - Acme\MyObj: - attributes: - foo: - groups: ['group1', 'group2'] - bar: - groups: ['group3'] - - .. code-block:: xml - - - - - - group1 - group2 - - - - group3 - - - - -You are now able to serialize only attributes in the groups you want:: - - use Symfony\Component\Serializer\Serializer; - use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; - - $obj = new MyObj(); - $obj->foo = 'foo'; - $obj->setBar('bar'); - - $normalizer = new ObjectNormalizer($classMetadataFactory); - $serializer = new Serializer(array($normalizer)); - - $data = $serializer->normalize($obj, null, array('groups' => array('group1'))); - // $data = array('foo' => 'foo'); - - $obj2 = $serializer->denormalize( - array('foo' => 'foo', 'bar' => 'bar'), - 'MyObj', - null, - array('groups' => array('group1', 'group3')) - ); - // $obj2 = MyObj(foo: 'foo', bar: 'bar') - -.. _ignoring-attributes-when-serializing: - -Ignoring Attributes -------------------- - -.. note:: - - Using attribute groups instead of the :method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes` - method is considered best practice. - -As an option, there's a way to ignore attributes from the origin object. To remove -those attributes use the -:method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes` +Sometimes property names from the serialized content are underscored (e.g. +``first_name``). Normally, these attributes will use get/set methods like +``getFirst_name``, when ``getFirstName`` method is what you really want. To +change that behavior use the +:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setCamelizedAttributes` method on the normalizer definition:: - use Symfony\Component\Serializer\Serializer; - use Symfony\Component\Serializer\Encoder\JsonEncoder; - use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; - - $normalizer = new ObjectNormalizer(); - $normalizer->setIgnoredAttributes(array('age')); $encoder = new JsonEncoder(); + $normalizer = new GetSetMethodNormalizer(); + $normalizer->setCamelizedAttributes(array('first_name')); $serializer = new Serializer(array($normalizer), array($encoder)); - $serializer->serialize($person, 'json'); // Output: {"name":"foo","sportsman":false} - -.. _component-serializer-converting-property-names-when-serializing-and-deserializing: - -Converting Property Names when Serializing and Deserializing ------------------------------------------------------------- - -Sometimes serialized attributes must be named differently than properties -or getter/setter methods of PHP classes. - -The Serializer Component provides a handy way to translate or map PHP field -names to serialized names: The Name Converter System. - -Given you have the following object:: - - class Company - { - public $name; - public $address; - } - -And in the serialized form, all attributes must be prefixed by ``org_`` like -the following:: - - {"org_name": "Acme Inc.", "org_address": "123 Main Street, Big City"} - -A custom name converter can handle such cases:: - - use Symfony\Component\Serializer\NameConverter\NameConverterInterface; - - class OrgPrefixNameConverter implements NameConverterInterface - { - public function normalize($propertyName) - { - return 'org_'.$propertyName; - } - - public function denormalize($propertyName) - { - // remove org_ prefix - return 'org_' === substr($propertyName, 0, 4) ? substr($propertyName, 4) : $propertyName; - } - } - -The custom normalizer can be used by passing it as second parameter of any -class extending :class:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer`, -including :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` -and :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`:: - use Symfony\Component\Serializer\Encoder\JsonEncoder - use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; - use Symfony\Component\Serializer\Serializer; - - $nameConverter = new OrgPrefixNameConverter(); - $normalizer = new ObjectNormalizer(null, $nameConverter); - - $serializer = new Serializer(array($normalizer), array(new JsonEncoder())); - - $obj = new Company(); - $obj->name = 'Acme Inc.'; - $obj->address = '123 Main Street, Big City'; - - $json = $serializer->serialize($obj); - // {"org_name": "Acme Inc.", "org_address": "123 Main Street, Big City"} - $objCopy = $serializer->deserialize($json); - // Same data as $obj - -.. _using-camelized-method-names-for-underscored-attributes: - -CamelCase to snake_case -~~~~~~~~~~~~~~~~~~~~~~~ - -In many formats, it's common to use underscores to separate words (also known -as snake_case). However, PSR-1 specifies that the preferred style for PHP -properties and methods is CamelCase. - -Symfony provides a built-in name converter designed to transform between -snake_case and CamelCased styles during serialization and deserialization -processes:: - - use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; - use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; - - $normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter()); - - class Person + $json = <<firstName = $firstName; - } - - public function getFirstName() - { - return $this->firstName; - } + "name": "foo", + "age": "19", + "first_name": "bar" } + EOT; - $kevin = new Person('Kévin'); - $normalizer->normalize($kevin); - // ['first_name' => 'Kévin']; - - $anne = $normalizer->denormalize(array('first_name' => 'Anne'), 'Person'); - // Person object with firstName: 'Anne' + $person = $serializer->deserialize($json, 'Acme\Person', 'json'); -Serializing Boolean Attributes ------------------------------- - -If you are using isser methods (methods prefixed by ``is``, like -``Acme\Person::isSportsman()``), the Serializer component will automatically -detect and use it to serialize related attributes. - -The ``ObjectNormalizer`` also takes care of methods starting with ``has``, ``add`` -and ``remove``. +As a final result, the deserializer uses the ``first_name`` attribute as if +it were ``firstName`` and uses the ``getFirstName`` and ``setFirstName`` methods. Using Callbacks to Serialize Properties with Object Instances ------------------------------------------------------------- @@ -478,178 +214,14 @@ When serializing, you can set a callback to format a specific object property:: $serializer->serialize($person, 'json'); // Output: {"name":"cordoval", "age": 34, "createdAt": "2014-03-22T09:43:12-0500"} -Normalizers ------------ - -There are several types of normalizers available: - -:class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer` - This normalizer leverages the :doc:`PropertyAccess Component ` - to read and write in the object. It means that it can access to properties - directly and through getters, setters, hassers, adders and removers. It supports - calling the constructor during the denormalization process. - - Objects are normalized to a map of property names (method name stripped of - the "get"/"set"/"has"/"remove" prefix and converted to lower case) to property - values. - - The ``ObjectNormalizer`` is the most powerful normalizer. It is a configured - by default when using the Symfony Standard Edition with the serializer enabled. - -:class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` - This normalizer reads the content of the class by calling the "getters" - (public methods starting with "get"). It will denormalize data by calling - the constructor and the "setters" (public methods starting with "set"). - - Objects are normalized to a map of property names (method name stripped of - the "get" prefix and converted to lower case) to property values. - -:class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer` - This normalizer directly reads and writes public properties as well as - **private and protected** properties. It supports calling the constructor - during the denormalization process. - - Objects are normalized to a map of property names to property values. - -Handling Circular References ----------------------------- - -Circular references are common when dealing with entity relations:: - - class Organization - { - private $name; - private $members; - - public function setName($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function setMembers(array $members) - { - $this->members = $members; - } - - public function getMembers() - { - return $this->members; - } - } - - class Member - { - private $name; - private $organization; - - public function setName($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function setOrganization(Organization $organization) - { - $this->organization = $organization; - } - - public function getOrganization() - { - return $this->organization; - } - } - -To avoid infinite loops, :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` -throws a :class:`Symfony\\Component\\Serializer\\Exception\\CircularReferenceException` -when such a case is encountered:: - - $member = new Member(); - $member->setName('Kévin'); - - $org = new Organization(); - $org->setName('Les-Tilleuls.coop'); - $org->setMembers(array($member)); - - $member->setOrganization($org); - - echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException - -The ``setCircularReferenceLimit()`` method of this normalizer sets the number -of times it will serialize the same object before considering it a circular -reference. Its default value is ``1``. - -Instead of throwing an exception, circular references can also be handled -by custom callables. This is especially useful when serializing entities -having unique identifiers:: - - $encoder = new JsonEncoder(); - $normalizer = new ObjectNormalizer(); - - $normalizer->setCircularReferenceHandler(function ($object) { - return $object->getName(); - }); - - $serializer = new Serializer(array($normalizer), array($encoder)); - var_dump($serializer->serialize($org, 'json')); - // {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"}]} - -Handling Arrays ---------------- - -The Serializer component is capable of handling arrays of objects as well. -Serializing arrays works just like serializing a single object:: - - use Acme\Person; - - $person1 = new Person(); - $person1->setName('foo'); - $person1->setAge(99); - $person1->setSportsman(false); - - $person2 = new Person(); - $person2->setName('bar'); - $person2->setAge(33); - $person2->setSportsman(true); - - $persons = array($person1, $person2); - $data = $serializer->serialize($persons, 'json'); - - // $data contains [{"name":"foo","age":99,"sportsman":false},{"name":"bar","age":33,"sportsman":true}] - -If you want to deserialize such a structure, you need to add the -:class:`Symfony\\Component\\Serializer\\Normalizer\\ArrayDenormalizer` -to the set of normalizers. By appending ``[]`` to the type parameter of the -:method:`Symfony\\Component\\Serializer\\Serializer::deserialize` method, -you indicate that you're expecting an array instead of a single object. - -.. code-block:: php - - use Symfony\Component\Serializer\Encoder\JsonEncoder; - use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; - use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; - use Symfony\Component\Serializer\Serializer; - - $serializer = new Serializer( - array(new GetSetMethodNormalizer(), new ArrayDenormalizer()), - array(new JsonEncoder()) - ); - - $data = ...; // The serialized data from the previous example - $persons = $serializer->deserialize($data, 'Acme\Person[]', 'json'); - -.. seealso:: +JMSSerializer +------------- - A popular alternative to the Symfony Serializer Component is the third-party - library, `JMS serializer`_ (released under the Apache license, so incompatible with GPLv2 projects). +A popular third-party library, `JMS serializer`_, provides a more +sophisticated albeit more complex solution. This library includes the +ability to configure how your objects should be serialized/deserialized via +annotations (as well as YAML, XML and PHP), integration with the Doctrine ORM, +and handling of other complex cases (e.g. circular references). .. _`JMS serializer`: https://github.com/schmittjoh/serializer .. _Packagist: https://packagist.org/packages/symfony/serializer diff --git a/components/stopwatch.rst b/components/stopwatch.rst index d2791f5bbb5..49b0876a6a5 100644 --- a/components/stopwatch.rst +++ b/components/stopwatch.rst @@ -7,6 +7,11 @@ The Stopwatch Component The Stopwatch component provides a way to profile code. +.. versionadded:: 2.2 + The Stopwatch component was introduced in Symfony 2.2. Previously, the + ``Stopwatch`` class was located in the HttpKernel component (and was introduced + in Symfony 2.1). + Installation ------------ @@ -34,12 +39,9 @@ microtime by yourself. Instead, use the simple $event = $stopwatch->stop('eventName'); The :class:`Symfony\\Component\\Stopwatch\\StopwatchEvent` object can be retrieved -from the :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, -:method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop`, -:method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` and -:method:`Symfony\\Component\\Stopwatch\\Stopwatch::getEvent` methods. -The latter should be used when you need to retrieve the duration of an event -while it is still running. +from the :method:`Symfony\\Component\\Stopwatch\\Stopwatch::start`, +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::stop` and +:method:`Symfony\\Component\\Stopwatch\\Stopwatch::lap` methods. You can also provide a category name to an event:: diff --git a/components/templating/helpers/assetshelper.rst b/components/templating/helpers/assetshelper.rst index 837b94255bc..d369214f8b2 100644 --- a/components/templating/helpers/assetshelper.rst +++ b/components/templating/helpers/assetshelper.rst @@ -47,20 +47,6 @@ You can also specify a URL to use in the second parameter of the constructor:: Now URLs are rendered like ``http://cdn.example.com/images/logo.png``. -You can also use the third argument of the helper to force an absolute URL: - -.. code-block:: html+php - - - - -.. note:: - - If you already set a URL in the constructor, using the third argument of - ``getUrl`` will not affect the generated URL. - Versioning ---------- @@ -77,16 +63,6 @@ is used in :phpfunction:`sprintf`. The first argument is the path and the second is the version. For instance, ``%s?v=%s`` will be rendered as ``/images/logo.png?v=328rad75``. -You can also generate a versioned URL on an asset-by-asset basis using the -fourth argument of the helper: - -.. code-block:: html+php - - - - Multiple Packages ----------------- diff --git a/components/translation/custom_formats.rst b/components/translation/custom_formats.rst index d5d9ddcd446..14c6e65c8b0 100644 --- a/components/translation/custom_formats.rst +++ b/components/translation/custom_formats.rst @@ -85,7 +85,7 @@ will save a few lines:: class MyFormatDumper extends FileDumper { - public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array()) + protected function format(MessageCatalogue $messages, $domain = 'messages') { $output = ''; @@ -102,14 +102,7 @@ will save a few lines:: } } -.. sidebar:: Format a message catalogue - - In some cases, you want to send the dump contents as a response instead of - writing them in files. To do this, you can use the ``formatCatalogue`` - method. In this case, you must pass the domain argument, which determines - the list of messages that should be dumped. - -The :method:`Symfony\\Component\\Translation\\Dumper\\FileDumper::formatCatalogue` +The :method:`Symfony\\Component\\Translation\\Dumper\\FileDumper::format` method creates the output string, that will be used by the :method:`Symfony\\Component\\Translation\\Dumper\\FileDumper::dump` method of the FileDumper class to create the file. The dumper can be used like any other @@ -123,3 +116,4 @@ YAML file are dumped into a text file with the custom format:: $dumper = new MyFormatDumper(); $dumper->dump($catalogue, array('path' => __DIR__.'/dumps')); + diff --git a/components/translation/introduction.rst b/components/translation/introduction.rst index 228597182b6..035d904be30 100644 --- a/components/translation/introduction.rst +++ b/components/translation/introduction.rst @@ -64,8 +64,7 @@ The Translation component uses Loader classes to load catalogs. You can load multiple resources for the same locale, which will then be combined into one catalog. -The component comes with some default Loaders and you can create your own -Loader too. The default loaders are: +The component comes with some default loaders: * :class:`Symfony\\Component\\Translation\\Loader\\ArrayLoader` - to load catalogs from PHP arrays. @@ -87,11 +86,14 @@ Loader too. The default loaders are: catalogs from QT XML files. * :class:`Symfony\\Component\\Translation\\Loader\\XliffFileLoader` - to load catalogs from Xliff files. -* :class:`Symfony\\Component\\Translation\\Loader\\JsonFileLoader` - to load - catalogs from JSON files. * :class:`Symfony\\Component\\Translation\\Loader\\YamlFileLoader` - to load catalogs from Yaml files (requires the :doc:`Yaml component`). +.. versionadded:: 2.1 + The ``IcuDatFileLoader``, ``IcuResFileLoader``, ``IniFileLoader``, + ``MoFileLoader``, ``PoFileLoader`` and ``QtFileLoader`` were introduced + in Symfony 2.1. + All file loaders require the :doc:`Config component `. You can also :doc:`create your own Loader `, diff --git a/components/translation/usage.rst b/components/translation/usage.rst index 00887e5bb12..c125e059510 100644 --- a/components/translation/usage.rst +++ b/components/translation/usage.rst @@ -139,8 +139,6 @@ recommended format. These files are parsed by one of the loader classes. 'symfony.great' => 'J\'aime Symfony', ); -.. _translation-real-vs-keyword-messages: - .. sidebar:: Using Real or Keyword Messages This example illustrates the two different philosophies when creating @@ -371,30 +369,5 @@ use for translation:: 'fr_FR' ); -Retrieving the Message Catalogue --------------------------------- - -In case you want to use the same translation catalogue outside your application -(e.g. use translation on the client side), it's possible to fetch raw translation -messages. Just specify the required locale:: - - $catalogue = $translator->getCatalogue('fr_FR'); - $messages = $catalogue->all(); - while ($catalogue = $catalogue->getFallbackCatalogue()) { - $messages = array_replace_recursive($catalogue->all(), $messages); - } - -The ``$messages`` variable will have the following structure:: - - array( - 'messages' => array( - 'Hello world' => 'Bonjour tout le monde', - ), - 'validators' => array( - 'Value should not be empty' => 'Valeur ne doit pas être vide', - 'Value is too long' => 'Valeur est trop long', - ), - ); - .. _`L10n`: https://en.wikipedia.org/wiki/Internationalization_and_localization .. _`ISO 31-11`: https://en.wikipedia.org/wiki/Interval_(mathematics)#Notations_for_intervals diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst deleted file mode 100644 index ccc0308cad7..00000000000 --- a/components/var_dumper/advanced.rst +++ /dev/null @@ -1,242 +0,0 @@ -.. index:: - single: VarDumper - single: Components; VarDumper - -Advanced Usage of the VarDumper Component -========================================= - -The ``dump()`` function is just a thin wrapper and a more convenient way to call -:method:`VarDumper::dump() `. -You can change the behavior of this function by calling -:method:`VarDumper::setHandler($callable) `. -Calls to ``dump()`` will then be forwarded to ``$callable``. - -By adding a handler, you can customize the `Cloners`_, `Dumpers`_ and `Casters`_ -as explained below. A simple implementation of a handler function might look -like this:: - - use Symfony\Component\VarDumper\VarDumper; - use Symfony\Component\VarDumper\Cloner\VarCloner; - use Symfony\Component\VarDumper\Dumper\CliDumper; - use Symfony\Component\VarDumper\Dumper\HtmlDumper; - - VarDumper::setHandler(function ($var) { - $cloner = new VarCloner(); - $dumper = 'cli' === PHP_SAPI ? new CliDumper() : new HtmlDumper(); - - $dumper->dump($cloner->cloneVar($var)); - }); - -Cloners -------- - -A cloner is used to create an intermediate representation of any PHP variable. -Its output is a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` -object that wraps this representation. - -You can create a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` -object this way:: - - use Symfony\Component\VarDumper\Cloner\VarCloner; - - $cloner = new VarCloner(); - $data = $cloner->cloneVar($myVar); - // this is commonly then passed to the dumper - // see the example at the top of this page - // $dumper->dump($data); - -A cloner also applies limits when creating the representation, so that the -corresponding Data object could represent only a subset of the cloned variable. -Before calling :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::cloneVar`, -you can configure these limits: - -:method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxItems` - configures the maximum number of items that will be cloned - *past the first nesting level*. Items are counted using a breadth-first - algorithm so that lower level items have higher priority than deeply nested - items; - -:method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxString` - configures the maximum number of characters that will be cloned before - cutting overlong strings; - -In both cases, specifying ``-1`` removes any limit. - -Before dumping it, you can further limit the resulting -:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object using the following methods: - -:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::withMaxDepth` - Allows limiting dumps in the depth dimension. - -:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::withMaxItemsPerDepth` - Limits the number of items per depth level. - -:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::withRefHandles` - Allows removing internal objects' handles for sparser output (useful for tests). - -Unlike the previous limits on cloners that remove data on purpose, these can -be changed back and forth before dumping since they do not affect the -intermediate representation internally. - -.. note:: - - When no limit is applied, a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` - object is as accurate as the native :phpfunction:`serialize` function, - and thus could be for purposes beyond dumping for debugging. - -Dumpers -------- - -A dumper is responsible for outputting a string representation of a PHP variable, -using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input. -The destination and the formatting of this output vary with dumpers. - -This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper` -for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper` -for optionally colored command line output. - -For example, if you want to dump some ``$variable``, just do:: - - use Symfony\Component\VarDumper\Cloner\VarCloner; - use Symfony\Component\VarDumper\Dumper\CliDumper; - - $cloner = new VarCloner(); - $dumper = new CliDumper(); - - $dumper->dump($cloner->cloneVar($variable)); - -By using the first argument of the constructor, you can select the output -stream where the dump will be written. By default, the ``CliDumper`` writes -on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``. But any PHP -stream (resource or URL) is acceptable. - -Instead of a stream destination, you can also pass it a ``callable`` that -will be called repeatedly for each line generated by a dumper. This -callable can be configured using the first argument of a dumper's constructor, -but also using the -:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setOutput` -method or the second argument of the -:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method. - -For example, to get a dump as a string in a variable, you can do:: - - use Symfony\Component\VarDumper\Cloner\VarCloner; - use Symfony\Component\VarDumper\Dumper\CliDumper; - - $cloner = new VarCloner(); - $dumper = new CliDumper(); - $output = ''; - - $dumper->dump( - $cloner->cloneVar($variable), - function ($line, $depth) use (&$output) { - // A negative depth means "end of dump" - if ($depth >= 0) { - // Adds a two spaces indentation to the line - $output .= str_repeat(' ', $depth).$line."\n"; - } - } - ); - - // $output is now populated with the dump representation of $variable - -Another option for doing the same could be:: - - use Symfony\Component\VarDumper\Cloner\VarCloner; - use Symfony\Component\VarDumper\Dumper\CliDumper; - - $cloner = new VarCloner(); - $dumper = new CliDumper(); - $output = fopen('php://memory', 'r+b'); - - $dumper->dump($cloner->cloneVar($variable), $output); - $output = stream_get_contents($output, -1, 0); - - // $output is now populated with the dump representation of $variable - -Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` -interface that specifies the -:method:`dump(Data $data) ` -method. They also typically implement the -:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees -them from re-implementing the logic required to walk through a -:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. - -Casters -------- - -Objects and resources nested in a PHP variable are "cast" to arrays in the -intermediate :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` -representation. You can tweak the array representation for each object/resource -by hooking a Caster into this process. The component already includes many -casters for base PHP classes and other common classes. - -If you want to build your own Caster, you can register one before cloning -a PHP variable. Casters are registered using either a Cloner's constructor -or its ``addCasters()`` method:: - - use Symfony\Component\VarDumper\Cloner\VarCloner; - - $myCasters = array(...); - $cloner = new VarCloner($myCasters); - - // or - - $cloner->addCasters($myCasters); - -The provided ``$myCasters`` argument is an array that maps a class, -an interface or a resource type to a callable:: - - $myCasters = array( - 'FooClass' => $myFooClassCallableCaster, - ':bar resource' => $myBarResourceCallableCaster, - ); - -As you can notice, resource types are prefixed by a ``:`` to prevent -colliding with a class name. - -Because an object has one main class and potentially many parent classes -or interfaces, many casters can be applied to one object. In this case, -casters are called one after the other, starting from casters bound to the -interfaces, the parents classes and then the main class. Several casters -can also be registered for the same resource type/class/interface. -They are called in registration order. - -Casters are responsible for returning the properties of the object or resource -being cloned in an array. They are callables that accept four arguments: - -* the object or resource being casted, -* an array modelled for objects after PHP's native ``(array)`` cast operator, -* a :class:`Symfony\\Component\\VarDumper\\Cloner\\Stub` object - representing the main properties of the object (class, type, etc.), -* true/false when the caster is called nested in a structure or not. - -Here is a simple caster not doing anything:: - - function myCaster($object, $array, $stub, $isNested) - { - // ... populate/alter $array to your needs - - return $array; - } - -For objects, the ``$array`` parameter comes pre-populated using PHP's native -``(array)`` casting operator or with the return value of ``$object->__debugInfo()`` -if the magic method exists. Then, the return value of one Caster is given -as the array argument to the next Caster in the chain. - -When casting with the ``(array)`` operator, PHP prefixes protected properties -with a ``\0*\0`` and private ones with the class owning the property. For example, -``\0Foobar\0`` will be the prefix for all private properties of objects of -type Foobar. Casters follow this convention and add two more prefixes: ``\0~\0`` -is used for virtual properties and ``\0+\0`` for dynamic ones (runtime added -properties not in the class declaration). - -.. note:: - - Although you can, it is advised to not alter the state of an object - while casting it in a Caster. - -.. tip:: - - Before writing your own casters, you should check the existing ones. diff --git a/components/var_dumper/index.rst b/components/var_dumper/index.rst deleted file mode 100644 index 2c67f2aa53f..00000000000 --- a/components/var_dumper/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -VarDumper -========= - -.. toctree:: - :maxdepth: 2 - - introduction - advanced diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst deleted file mode 100644 index 3d162b7d328..00000000000 --- a/components/var_dumper/introduction.rst +++ /dev/null @@ -1,274 +0,0 @@ -.. index:: - single: VarDumper - single: Components; VarDumper - -The VarDumper Component -======================= - - The VarDumper component provides mechanisms for walking through any - arbitrary PHP variable. Built on top, it provides a better ``dump()`` - function that you can use instead of :phpfunction:`var_dump`. - -Installation ------------- - -You can install the component in 2 different ways: - -* :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/var-dumper). - -.. note:: - - If using it inside a Symfony application, make sure that the - DebugBundle is enabled in your ``app/AppKernel.php`` file. - -.. _components-var-dumper-dump: - -The dump() Function -------------------- - -The VarDumper component creates a global ``dump()`` function that you can -use instead of e.g. :phpfunction:`var_dump`. By using it, you'll gain: - -* Per object and resource types specialized view to e.g. filter out - Doctrine internals while dumping a single proxy entity, or get more - insight on opened files with :phpfunction:`stream_get_meta_data`; -* Configurable output formats: HTML or colored command line output; -* Ability to dump internal references, either soft ones (objects or - resources) or hard ones (``=&`` on arrays or objects properties). - Repeated occurrences of the same object/array/resource won't appear - again and again anymore. Moreover, you'll be able to inspect the - reference structure of your data; -* Ability to operate in the context of an output buffering handler. - -For example:: - - require __DIR__.'/vendor/autoload.php'; - - // create a variable, which could be anything! - $someVar = ...; - - dump($someVar); - -By default, the output format and destination are selected based on your -current PHP SAPI: - -* On the command line (CLI SAPI), the output is written on ``STDOUT``. This - can be surprising to some because this bypasses PHP's output buffering - mechanism; -* On other SAPIs, dumps are written as HTML in the regular output. - -.. note:: - - If you want to catch the dump output as a string, please read the - `advanced documentation `_ which contains examples of it. - You'll also learn how to change the format or redirect the output to - wherever you want. - -.. tip:: - - In order to have the ``dump()`` function always available when running - any PHP code, you can install it globally on your computer: - - #. Run ``composer global require symfony/var-dumper``; - #. Add ``auto_prepend_file = ${HOME}/.composer/vendor/autoload.php`` - to your ``php.ini`` file; - #. From time to time, run ``composer global update symfony/var-dumper`` - to have the latest bug fixes. - -DebugBundle and Twig Integration --------------------------------- - -The DebugBundle allows greater integration of the component into the Symfony -full-stack framework. It is enabled by default in the *dev* and *test* -environment of the Symfony Standard Edition. - -Since generating (even debug) output in the controller or in the model -of your application may just break it by e.g. sending HTTP headers or -corrupting your view, the bundle configures the ``dump()`` function so that -variables are dumped in the web debug toolbar. - -But if the toolbar can not be displayed because you e.g. called ``die``/``exit`` -or a fatal error occurred, then dumps are written on the regular output. - -In a Twig template, two constructs are available for dumping a variable. -Choosing between both is mostly a matter of personal taste, still: - -* ``{% dump foo.bar %}`` is the way to go when the original template output - shall not be modified: variables are not dumped inline, but in the web - debug toolbar; -* on the contrary, ``{{ dump(foo.bar) }}`` dumps inline and thus may or not - be suited to your use case (e.g. you shouldn't use it in an HTML - attribute or a ``