![]() |
|
Symfony tutorialWhat's new in symfony 1.3/1.4? |
|

You are currently reading "symfony Tutorials" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.
sfWidgetFormInputText sfValidatorRegex sfValidatorUrl sfValidatorSchemaCompare sfValidatorChoice, sfValidatorPropelChoice, sfValidatorDoctrineChoice sfValidatorFile sfForm::useFields() sfForm::getEmbeddedForm($name) sfForm::renderHiddenFields() sfFormSymfony BaseForm sfForm::doBind() sfForm(Doctrine|Propel)::doUpdateObject() sfForm::enableLocalCSRFProtection() and sfForm::disableLocalCSRFProtection() sfAutoloadAgain (EXPERIMENTAL) sfTesterResponse::checkForm() sfTesterResponse::isValid() context.load_factories ->click() sfTask::askAndValidate() symfony:test project:deploy generate:project sfFileSystem::execute() task.test.filter_test_files sfTask::run() sfBaseTask::setConfiguration() project:disable and project:enable help and list project:optimize generate:app propel:insert-sql propel:generate-module, propel:generate-admin, propel:generate-admin-for-route sfObjectRouteCollection options sfPluginConfiguration::connectTests() sf_file_link_format doctrine:migrate --down doctrine:migrate --dry-run doctrine:dql sfFormFilterDoctrine doctrine:generate-module, doctrine:generate-admin, doctrine:generate-admin-for-route sfWebDebugPanel::setStatus() sfWebDebugPanel request parameter getContent() PUT and DELETE parameters redirect() link_to_if(), link_to_unless()
|
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License. |
This tutorial is a quick technical introduction for symfony 1.3/1.4. It is for developers who have already worked with symfony 1.2 and who want to quickly learn new features of symfony 1.3/1.4.
First, please note that symfony 1.3 is compatible with PHP 5.2.4 or later.
If you want to upgrade from 1.2, please read the UPGRADE file found in the symfony distribution. You will have there all the information needed to safely upgrade your projects to symfony 1.3.
As of symfony 1.3/1.4, there is a new default mailer based on SwiftMailer 4.1.
Sending an email is as simple as using the composeAndSend() method from an
action:
$this->getMailer()->composeAndSend('from@example.com', 'to@example.com', 'Subject', 'Body');
If you need to have more flexibility, you can also use the compose() method
and send it afterwards. Here is for instance how to add an attachment to the
message:
$message = $this->getMailer()-> compose('from@example.com', 'to@example.com', 'Subject', 'Body')-> attach(Swift_Attachment::fromPath('/path/to/a/file.zip')) ; $this->getMailer()->send($message);
As the mailer is quite powerful, refer to the documentation for more information.
When a new application is created with the generate:app task, the security
settings are now enabled by default:
escaping_strategy: The value is now true by default (can be disabled
with the --escaping-strategy option).
csrf_secret: A random password is generated by default, and thus, the
CSRF protection is enabled by default (can be disabled with the
--csrf-secret option). It is highly recommended that you change the
default generated password, by editing the settings.yml configuration
file, or by using the --csrf-secret option.
When a label is auto-generated from the field name, _id suffixes are now
removed:
first_name => First name (as before)author_id => Author (was "Author id" before)sfWidgetFormInputTextThe sfWidgetFormInput class is now abstract. Text input fields are now
created with the sfWidgetFormInputText class. This change was made to ease
introspection of form classes.
The following widgets have been added:
sfWidgetFormI18nChoiceLanguagesfWidgetFormI18nChoiceCurrencysfWidgetFormI18nChoiceCountrysfWidgetFormI18nChoiceTimezoneThe first three of them replace the now deprecated
sfWidgetFormI18nSelectLanguage, sfWidgetFormI18nSelectCurrency, and
sfWidgetFormI18nSelectCountry widgets.
The widgets now implement a fluid interface for the following methods:
sfWidgetForm: setDefault(), setLabel(), setIdFormat(),
setHidden()
sfWidget: addRequiredOption(), addOption(), setOption(),
setOptions(), setAttribute(), setAttributes()
sfWidgetFormSchema: setDefault(), setDefaults(),
addFormFormatter(), setFormFormatterName(), setNameFormat(),
setLabels(), setLabel(), setHelps(), setHelp(), setParent()
sfWidgetFormSchemaDecorator: addFormFormatter(),
setFormFormatterName(), setNameFormat(), setLabels(), setHelps(),
setHelp(), setParent(), setPositions()
sfValidatorRegexThe sfValidatorRegex has a new must_match option. If set to false, the
regex must not match for the validator to pass.
The pattern option of sfValidatorRegex can now be an instance of
sfCallable that returns a regex when called.
sfValidatorUrlThe sfValidatorUrl has a new protocols option. This allows you to specify
what protocols to allow:
$validator = new sfValidatorUrl(array('protocols' => array('http', 'https')));
The following protocols are allowed by default:
httphttpsftpftpssfValidatorSchemaCompareThe sfValidatorSchemaCompare class has two new comparators:
IDENTICAL, which is equivalent to ===;NOT_IDENTICAL, which is equivalent to !==;sfValidatorChoice, sfValidatorPropelChoice, sfValidatorDoctrineChoiceThe sfValidatorChoice, sfValidatorPropelChoice,
sfValidatorDoctrineChoice validators have two new options that are enabled
only if the multiple option is true:
min The minimum number of values that need to be selectedmax The maximum number of values that need to be selectedThe following validators have been added:
sfValidatorI18nChoiceTimezoneYou can now define default error messages globally by using the
sfValidatorBase::setDefaultMessage() method:
sfValidatorBase::setDefaultMessage('required', 'This field is required.');
The previous code will override the default 'Required.' message for all validators. Note that the default messages must be defined before any validator is created (the configuration class is a good place).
The
setRequiredMessage()andsetInvalidMessage()methods are deprecated and call the newsetDefaultMessage()method.
When symfony displays an error, the error message to use is determined as follows:
Symfony looks for a message passed when the validator was created (via the second argument of the validator constructor);
If it is not defined, it looks for a default message defined with
the setDefaultMessage() method;
If it is not defined, it falls back to the default message defined by the
validator itself (when the message has been added with the addMessage()
method).
The validators now implement a fluid interface for the following methods:
sfValidatorSchema: setPreValidator(), setPostValidator()
sfValidatorErrorSchema: addError(), addErrors()
sfValidatorBase: addMessage(), setMessage(), setMessages(),
addOption(), setOption(), setOptions(), addRequiredOption()
sfValidatorFileAn exception is thrown when creating an instance of sfValidatorFile if
file_uploads is disabled in php.ini.
sfForm::useFields()The new sfForm::useFields() method removes all non-hidden fields from a form
except the ones given as an argument. It is sometimes easier to explicitly
give the fields you want to keep in a form, instead of unsetting all unneeded
fields. For instance, when adding new fields to a base form, they won't
automagically appear in your form until explicitly added (think of a model
form where you add a new column to the related table).
class ArticleForm extends BaseArticleForm { public function configure() { $this->useFields(array('title', 'content')); } }
By default, the array of fields is also used to change the fields order. You
can pass false as the second argument to useFields() to disable the
automatic reordering.
sfForm::getEmbeddedForm($name)You can now access a particular embedded form using the ->getEmbeddedForm()
method.
sfForm::renderHiddenFields()The ->renderHiddenFields() method now renders hidden fields from embedded
forms. An argument has been added to disable recursion, useful if you render
embedded forms using a formatter.
// render all hidden fields, including those from embedded forms echo $form->renderHiddenFields(); // render hidden fields without recurring echo $form->renderHiddenFields(false);
sfFormSymfonyThe new sfFormSymfony class introduces the event dispatcher to symfony
forms. You can access the dispatcher from inside your form classes as
self::$dispatcher. The following form events are now notified by symfony:
form.post_configure: This event is notified after every form is
configuredform.filter_values: This event filters the merged, tainted parameters
and files array just prior to bindingform.validation_error: This event is notified whenever form validation
failsform.method_not_found: This event is notified whenever an unknown method
is calledBaseFormEvery new symfony 1.3/1.4 project includes a BaseForm class that you can use to
extend the Form component or add project-specific functionality. The forms
generated by sfDoctrinePlugin and sfPropelPlugin automatically extend this
class. If you create additional form classes they should now extend BaseForm
rather than sfForm.
sfForm::doBind()The cleaning of tainted parameters has been isolated in a developer-friendly
method, ->doBind(), which receives the merged array of parameters and files
from ->bind().
sfForm(Doctrine|Propel)::doUpdateObject()The Doctrine and Propel form classes now include a developer-friendly
->doUpdateObject() method. This method receives an array of values from
->updateObject() that has already been processed by ->processValues().
sfForm::enableLocalCSRFProtection() and sfForm::disableLocalCSRFProtection()Using the sfForm::enableLocalCSRFProtection() and
sfForm::disableLocalCSRFProtection() methods, you can now easily configure
the CSRF protection from the configure() method of your form classes.
To disable the CSRF protection for a form, add the following line in its
configure() method:
$this->disableLocalCSRFProtection();
By calling the disableLocalCSRFProtection(), the CSRF protection will be
disabled, even if you pass a CSRF secret when creating a form instance.
Some sfForm methods now implement a fluent interface: addCSRFProtection(),
setValidators(), setValidator(), setValidatorSchema(), setWidgets(),
setWidget(), setWidgetSchema(), setOption(), setDefault(), and
setDefaults().
All symfony autoloaders are now case-insensitive. PHP is case-insensitive, now so is symfony.
sfAutoloadAgain (EXPERIMENTAL)A special autoloader has been added that is just for use in debug mode. The
new sfAutoloadAgain class will reload the standard symfony autoloader and
search the filesystem for the class in question. The net effect is that you no
longer have to run symfony cc after adding a new class to a project.
When you have a large suite of tests, it can be very time consuming to launch
all tests every time you make a change, especially if some tests fail. That's
because each time you fix a test, you should run the whole test suite again to
ensure that you have not break something else. But as long as the failed tests
are not fixed, there is no point in re-executing all other tests. As of
symfony 1.3/1.4, the test:all and symfony:test tasks have a --only-failed
(-f as a shortcut) option that forces the task to only re-execute tests that
failed during the previous run:
$ php symfony test:all --only-failed
Here is how it works: the first time, all tests are run as usual. But for subsequent test runs, only tests that failed last time are executed. As you fix your code, some tests will pass, and will be removed from subsequent runs. When all tests pass again, the full test suite is run... you can then rinse and repeat.
When a request generates an exception, the debug() method of the response
tester now outputs a readable text representation of the exception, instead of
the normal HTML output. It makes debugging much easier.
sfTesterResponse has a new matches() method that runs a regex on the whole
response content. It is of great help on non XML-like responses, where
checkElement() is not useable. It also replaces the less-powerful
contains() method:
$browser->with('response')->begin()-> matches('/I have \d+ apples/')-> // it takes a regex as an argument matches('!/I have \d+ apples/')-> // a ! at the beginning means that the regex must not match matches('!/I have \d+ apples/i')-> // you can also add regex modifiers end();
The test tasks are now able to output a JUnit compatible XML file by using the
--xml option:
$ php symfony test:all --xml=log.xml
To ease the debugging when a test harness reports failed tests, you can now
pass the --trace option to have a detailed output about the failures:
$ php symfony test:all -t
As of symfony 1.3/1.4, lime does the right thing as far as colorization is
concerned. It means, that you can almost always omit the second argument of
the lime constructor of lime_test:
$t = new lime_test(1);
sfTesterResponse::checkForm()The response tester now includes a method to easily verify that all fields in a form have been rendered to the response:
$browser->with('response')->begin()-> checkForm('ArticleForm')-> end();
Or, if you prefer, you can pass a form object:
$browser->with('response')->begin()-> checkForm($browser->getArticleForm())-> end();
If the response includes multiple forms you have the option of providing a CSS selector to pinpoint which portion of the DOM to test:
$browser->with('response')->begin()-> checkForm('ArticleForm', '#articleForm')-> end();
sfTesterResponse::isValid()You can now check whether a response is well-formed XML with the response
tester's ->isValid() method:
$browser->with('response')->begin()-> isValid()-> end();
You also validate the response against its document type be passing true as an
argument:
$browser->with('response')->begin()-> isValid(true)-> end();
Alternatively, if you have a XSD or RelaxNG schema to validate against, you can provide the path to this file:
$browser->with('response')->begin()-> isValid('/path/to/schema.xsd')-> end();
context.load_factoriesYou can now add listeners for the context.load_factories event to your
functional tests. This was not possible in previous versions of symfony.
$browser->addListener('context.load_factories', array($browser, 'listenForNewContext'));
->click()You can now pass any CSS selector to the ->click() method, making it much
easier to target the element you want semantically.
$browser ->get('/login') ->click('form[action$="/login"] input[type="submit"]') ;
The symfony CLI now attempts to detect the width of your terminal window and formats lines to fit. If detection is not possible the CLI defaults to 78 columns wide.
sfTask::askAndValidate()There is a new sfTask::askAndValidate() method to ask a question to the user
and validates its input:
$answer = $this->askAndValidate('What is you email?', new sfValidatorEmail());
The method also accepts an array of options (see the API doc for more information).
symfony:testFrom time to time, developers need to run the symfony test suite to check that
symfony works well on their specific platform. Until now, they had to know the
prove.php script bundled with symfony to do that. As of symfony 1.3/1.4, there
is a built-in task, symfony:test that launches the symfony core test suite
from the command line, like any other task:
$ php symfony symfony:test
If you were used to run php test/bin/prove.php, you should now run the
equivalent php data/bin/symfony symfony:test command.
project:deployThe project:deploy task has been slightly improved. It now displays the
progress of the files transfer in real-time, but only if the -t option is
passed. If not, the task is silent, except for errors of course. Speaking of
errors, if one occurs, the output is on a red background to ease problem
identification.
generate:projectAs of symfony 1.3/1.4, Doctrine is the default configured ORM when executing the
generate:project task:
$ php /path/to/symfony generate:project foo
To generate a project for Propel, use the --orm option:
$ php /path/to/symfony generate:project foo --orm=Propel
If you don't want to use Propel or Doctrine, you can pass none to the
--orm option:
$ php /path/to/symfony generate:project foo --orm=none
The new --installer option allows you to pass a PHP script that can further
customize the newly created project. The script is executed in the context of
the task, and so can use any of its methods. The more useful ones are the
following: installDir(), runTask(), ask(), askConfirmation(),
askAndValidate(), reloadTasks(), enablePlugin(), and disablePlugin().
More information can be found in this post from the official symfony blog.
You can also include a second "author" argument when generating a project,
which specifies a value to use for the @author doc tag when symfony
generates new classes.
$ php /path/to/symfony generate:project foo "Joe Schmo"
sfFileSystem::execute()The sfFileSystem::execute() methods replaces the sfFileSystem::sh() method
with more powerful features. It takes callbacks for real-time processing of
the stdout and stderr outputs. It also returns both outputs as an array.
You can find one example of its usage in the sfProjectDeployTask class.
task.test.filter_test_filesThe test:* tasks now filter test files through the
task.test.filter_test_files event prior to running them. This event includes
arguments and options parameters.
sfTask::run()You can now pass an associative array of arguments and options to
sfTask::run():
$task = new sfDoctrineConfigureDatabaseTask($this->dispatcher, $this->formatter); $task->run( array('dsn' => 'mysql:dbname=mydb;host=localhost'), array('name' => 'master') );
The previous version, which still works:
$task->run( array('mysql:dbname=mydb;host=localhost'), array('--name=master') );
sfBaseTask::setConfiguration()When calling a task that extends sfBaseTask from PHP, you no longer have to
pass --application and --env options to ->run(). Instead, you can simply
set the configuration object directly by calling ->setConfiguration().
$task = new sfDoctrineLoadDataTask($this->dispatcher, $this->formatter); $task->setConfiguration($this->configuration); $task->run();
The previous version, which still works:
$task = new sfDoctrineLoadDataTask($this->dispatcher, $this->formatter); $task->run(array(), array( '--application='.$options['application'], '--env='.$options['env'], ));
project:disable and project:enableYou can now wholesale disable or enable an entire environment using the
project:disable and project:enable tasks:
$ php symfony project:disable prod
$ php symfony project:enable prod
You can also specify which applications to disable in that environment:
$ php symfony project:disable prod frontend backend
$ php symfony project:enable prod frontend backend
These tasks are backward compatible with their previous signature:
$ php symfony project:disable frontend prod
$ php symfony project:enable frontend prod
help and listThe help and list tasks can now display their information as XML:
$ php symfony list --xml
$ php symfony help test:all --xml
The output is based on the new sfTask::asXml() method, which returns a XML
representation of a task object.
The XML output is mostly useful for third-party tools like IDEs.
project:optimizeRunning this task reduces the number of disk reads performed during runtime by caching the location of your application's template files. This task should only be used on a production server. Don't forget to re-run the task each time the project changes.
$ php symfony project:optimize frontend
generate:appThe generate:app task now checks for a skeleton directory in your project's
data/skeleton/app directory before defaulting to the skeleton bundled in the
core.
You can now easily send an email from a task by using the getMailer()
method.
You can now easily get the routing object from a task by using the
getRouting() method.
When an exception is thrown during autoloading, symfony now catches them and outputs an error to the user. That should solve some "White screen of death" pages.
If possible, the web debug toolbar is now also displayed on exception pages in the development environment.
Propel has been upgraded to version 1.4. Please visit Propel's site for more information on their upgrade (http://propel.phpdb.org/trac/wiki/Users/Documentation/1.4).
The custom builder classes symfony has relied on to extend Propel have been ported to Propel 1.4's new behaviors system.
propel:insert-sqlBefore propel:insert-sql removes all data from a database, it asks for a
confirmation. As this task can remove data from several databases, it now also
displays the name of the connections of the related databases.
propel:generate-module, propel:generate-admin, propel:generate-admin-for-routeThe propel:generate-module, propel:generate-admin, and
propel:generate-admin-for-route tasks now takes a --actions-base-class option that allows
the configuration of the actions base class for the generated modules.
Propel 1.4 introduced an implementation of behaviors in the Propel codebase. The custom symfony builders have been ported into this new system.
If you would like to add native behaviors to your Propel models, you can do so
in schema.yml:
classes:
Article:
propel_behaviors:
timestampable: ~
Or, if you use the old schema.yml syntax:
propel:
article:
_propel_behaviors:
timestampable: ~
You can now disable form generation on certain models by passing parameters to
the symfony Propel behavior:
classes:
UserGroup:
propel_behaviors:
symfony:
form: false
filter: false
Note that you have to rebuild the model before that setting is respected, because the behaviour is attached to the model and does only exist after rebuilding it.
Using a different version of propel is as easy as setting the
sf_propel_runtime_path and sf_propel_generator_path config variables in
ProjectConfiguration:
// config/ProjectConfiguration.class.php public function setup() { $this->enablePlugins('sfPropelPlugin'); sfConfig::set('sf_propel_runtime_path', '/path/to/propel/runtime'); sfConfig::set('sf_propel_generator_path', '/path/to/propel/generator'); }
The default \d+ requirement is now only applied to a
sfObjectRouteCollection when the column option is the default id. This
means you no longer have to provide an alternate requirement when a
non-numeric column is specified (i.e. slug).
sfObjectRouteCollection optionsA new default_params option has been added to sfObjectRouteCollection. It
allows for default parameters to be registered for each generated route:
forum_topic:
class: sfDoctrineRouteCollection
options:
default_params:
section: forum
Symfony tries to guess if your console supports colors when you use the symfony CLI tool. But sometimes, symfony guesses wrong; for instance when you use Cygwin (because colorization is always turned off on the Windows platform).
As of symfony 1.3/1.4, you can force the use of colors for the output by passing
the global --color option.
The data used for all I18N operations was updated from the ICU project.
Symfony comes now with about 330 locale files, which is an increase of about 70
compared to Symfony 1.2. Please note that the updated data might be slightly
different from what has been in there before, so for example test cases checking
for the tenth item in a language list might fail.
All sorting on this locale dependent data is now also performed locale dependent.
sfCultureInfo->sortArray() can be used for that.
Before symfony 1.3/1.4, all plugins were enabled by default, except for the
sfDoctrinePlugin and the sfCompat10Plugin ones:
class ProjectConfiguration extends sfProjectConfiguration { public function setup() { // for compatibility / remove and enable only the plugins you want $this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin')); } }
For freshly created projects with symfony 1.3/1.4, plugins must be explicitly
enabled in the ProjectConfiguration class to be able to use them:
class ProjectConfiguration extends sfProjectConfiguration { public function setup() { $this->enablePlugins('sfDoctrinePlugin'); } }
The plugin:install task automatically enables the plugin(s) it installs (and
plugin:uninstall disable them). If you install a plugin via Subversion, you
still need to enable it by hand.
If you want to use a core-plugin, like sfProtoculousPlugin or
sfCompat10Plugin, you just need to add the corresponding enablePlugins()
statement in the ProjectConfiguration class.
If you upgrade a project from 1.2, the old behavior will still be active as the upgrade task does not change the
ProjectConfigurationfile. The behavior change is only for new symfony 1.3/1.4 projects.
sfPluginConfiguration::connectTests()You can connect a plugin's tests to the test:* tasks by calling that plugin
configuration's ->connectTests() method in the new setupPlugins() method:
class ProjectConfiguration extends sfProjectConfiguration { public function setupPlugins() { $this->pluginConfigurations['sfExamplePlugin']->connectTests(); } }
sf_file_link_formatSymfony 1.3/1.4 formats file paths as clickable links whenever possible (i.e. the
debug exception template). The sf_file_link_format is used for this purpose,
if set, otherwise symfony will look for the xdebug.file_link_format PHP
configuration value.
For example, if you want to open files in TextMate, add the following to
settings.yml:
all:
.settings:
file_link_format: txmt://open?url=file://%f&line=%l
The %f placeholder will be replaced with file's absolute path and the %l
placeholder will be replaced with the line number.
Doctrine has been upgraded to version 1.2. Please visit Doctrine's site for more information on their upgrade (http://www.doctrine-project.org/documentation/1_2/en).
It is now possible to specify additional options for symfony in your Doctrine YAML schema files. We've added some options to disable the generation of form and filter classes.
For example in a typical many to many reference model, you don't need any form or filter form classes generated. So you can now do the following:
UserGroup:
options:
symfony:
form: false
filter: false
columns:
user_id:
type: integer
primary: true
group_id:
type: integer
primary: true
When you generate forms from your models, your models contain inheritance. The generated child classes will respect the inheritance and generate forms that follow the same inheritance structure.
We have introduced a few new tasks to help you when developing with Doctrine.
You can now individually create the tables for a specified array of models. It will drop the tables first then re-create them for you. This is useful if you are developing some new models in an existing project/database and you don't want to blow away the whole database and just want to rebuild a subset of tables.
$ php symfony doctrine:create-model-tables Model1 Model2 Model3
Often you will change your models, renaming things, remove unused models, etc.
in your YAML schema files. When you do this, you then have orphaned model, form
and filter classes. You can now manually clean out the generated files related
to a model by using the doctrine:delete-model-files task.
$ php symfony doctrine:delete-model-files ModelName
The above task will find all the related generated files and report them to you before asking you to confirm whether you would like to delete the files or not.
You can automate the above process and find out what models exist on the disk
but do not exist in your YAML schema files by using the doctrine:clean-model-files
task.
$ php symfony doctrine:clean-model-files
The above command will compare your YAML schema files with the models and files
that have been generated and determine what should be removed. These models are
then passed on to the doctrine:delete-model-files task. It will ask you to
confirm the removal of any files before actually deleting anything.
The new doctrine:build task allows you to specify what exactly you would
like symfony and Doctrine to build. This task replicates the functionality in
many of the existing combination-tasks, which have all been deprecated in
favor of this more flexible solution.
Here are some possible uses of doctrine:build:
$ php symfony doctrine:build --db --and-load
This will drop (:drop-db) and create (:build-db) the database, create the
tables configured in schema.yml (:insert-sql) and load the fixture data
(:data-load).
$ php symfony doctrine:build --all-classes --and-migrate
This will build the model (:build-model), forms (:build-forms), form
filters (:build-filters) and run any pending migrations (:migrate).
$ php symfony doctrine:build --model --and-migrate --and-append=data/fixtures/categories.yml
This will build the model (:build-model), migrate the database (:migrate)
and append category fixtures data (:data-load --append --dir=data/fixtures/categories.yml).
For more information see the doctrine:build task's help page.
--migrateThe following tasks now include a --migrate option, which will replace the
nested doctrine:insert-sql task with doctrine:migrate.
doctrine:build-alldoctrine:build-all-loaddoctrine:build-all-reloaddoctrine:build-all-reload-test-alldoctrine:rebuild-dbdoctrine:reload-datadoctrine:generate-migration --editor-cmdThe doctrine:generate-migration task now includes a --editor-cmd option
which will execute once the migration class is created for easy editing.
$ php symfony doctrine:generate-migration AddUserEmailColumn --editor-cmd=mate
This example will generate the new migration class and open the new file in TextMate.
doctrine:generate-migrations-diffThis new task will automatically generate complete migration classes for you, based on your old and new schemas.
You can now specify database connection names when running doctrine:build-db
and doctrine:drop-db:
$ php symfony doctrine:drop-db master slave1 slave2
We've added two new methods for retrieving Doctrine date or timestamp values as PHP DateTime object instances.
echo $article->getDateTimeObject('created_at') ->format('m/d/Y');
You can also set a dates value by simply calling the setDateTimeObject method
and passing a valid DateTime instance.
$article->setDateTimeObject('created_at', new DateTime('09/01/1985'));
doctrine:migrate --downThe doctrine:migrate now includes up and down options that will migrate
your schema one step in the requested direction.
$ php symfony doctrine:migrate --down
doctrine:migrate --dry-runIf your database supports rolling back DDL statements (MySQL does not), you
can take advantage of the new dry-run option.
$ php symfony doctrine:migrate --dry-run
When you would previously run the doctrine:dql command it will just output the
data as YAML. We have added a new --table option. This option allows you to
output the data as a table, similar to how it ouputs in the MySQL command line.
So now the following is possible.
$ ./symfony doctrine:dql "FROM Article a" --table
>> doctrine executing dql query
DQL: FROM Article a
+----+-----------+----------------+---------------------+---------------------+
| id | author_id | is_on_homepage | created_at | updated_at |
+----+-----------+----------------+---------------------+---------------------+
| 1 | 1 | | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 |
| 2 | 2 | | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 |
+----+-----------+----------------+---------------------+---------------------+
(2 results)
doctrine:dqlThe doctrine:dql task has also been enhanced to accept query parameters as
arguments:
$ php symfony doctrine:dql "FROM Article a WHERE name LIKE ?" John%
The sfTesterDoctrine class now includes a ->debug() method. This method
will output information about that queries that have been run in the current
context.
$browser-> get('/articles')-> with('doctrine')->debug() ;
You can view only the last few queries executed by passing an integer to the method, or show only queries that contain a substring or match a regular expression by passing a string.
$browser-> get('/articles')-> with('doctrine')->debug('/from articles/i') ;
sfFormFilterDoctrineThe sfFormFilterDoctrine class can now be seeded a Doctrine_Query object
via the query option:
$filter = new ArticleFormFilter(array(), array( 'query' => $table->createQuery()->select('title, body'), ));
The table method specified via ->setTableMethod() (or now via the
table_method option) is no longer required to return a query object. Any of
the following are valid sfFormFilterDoctrine table methods:
// works in symfony >= 1.2 public function getQuery() { return $this->createQuery()->select('title, body'); } // works in symfony >= 1.2 public function filterQuery(Doctrine_Query $query) { return $query->select('title, body'); } // works in symfony >= 1.3 public function modifyQuery(Doctrine_Query $query) { $query->select('title, body'); }
Customizing a form filter is now easier. To add a filtering field, all you have to do is add the widget and a method to process it.
class UserFormFilter extends BaseUserFormFilter { public function configure() { $this->widgetSchema['name'] = new sfWidgetFormInputText(); $this->validatorSchema['name'] = new sfValidatorString(array('required' => false)); } public function addNameColumnQuery($query, $field, $value) { if (!empty($value)) { $query->andWhere(sprintf('CONCAT(%s.f_name, %1$s.l_name) LIKE ?', $query->getRootAlias()), $value); } } }
In earlier versions you would have need to extend getFields() in addition to
creating a widget and method to get this to work.
You can now listen to the events doctrine.configure and
doctrine.configure_connection to configure Doctrine. This means the Doctrine
configuration can be easily customized from a plugin, as long as the plugin is
enabled prior to sfDoctrinePlugin.
doctrine:generate-module, doctrine:generate-admin, doctrine:generate-admin-for-routeThe doctrine:generate-module, doctrine:generate-admin, and
doctrine:generate-admin-for-route tasks now takes a --actions-base-class option that allows
the configuration of the actions base class for the generated modules.
The magic getter and setter methods symfony adds to your Doctrine models are
now represented in the doc header of each generated base class. If your IDE
supports code completion, you should now see these getFooBar() and
setFooBar() methods show up on model objects, where FooBar is a CamelCased
field name.
Using a different version of Doctrine is as easy as setting the
sf_doctrine_dir setting in ProjectConfiguration:
// config/ProjectConfiguration.class.php public function setup() { $this->enablePlugins('sfDoctrinePlugin'); sfConfig::set('sf_doctrine_dir', '/path/to/doctrine/lib'); }
sfWebDebugPanel::setStatus()Each panel in the web debug toolbar can specify a status that will affect its
title's background color. For example, the background color of the log panel's
title changes if any messages with a priority greater than sfLogger::INFO
are logged.
sfWebDebugPanel request parameterYou can now specify a panel to be open on page load by appending a
sfWebDebugPanel parameter to the URL. For example, appending
?sfWebDebugPanel=config would cause the web debug toolbar to render with the
config panel open.
Panels can also inspect request parameters by accessing the web debug
request_parameters option:
$requestParameters = $this->webDebug->getOption('request_parameters');
The get_slot() and include_slot() helpers now accept a second parameter for
specifying the default slot content to return if none is provided by the slot:
<?php echo get_slot('foo', 'bar') // will output 'bar' if slot 'foo' is not defined ?> <?php include_slot('foo', 'bar') // will output 'bar' if slot 'foo' is not defined ?>
The sfDoctrinePager and sfPropelPager methods now implement the Iterator
and Countable interfaces.
<?php if (count($pager)): ?> <ul> <?php foreach ($pager as $article): ?> <li><?php echo link_to($article->getTitle(), 'article_show', $article) ?></li> <?php endforeach; ?> </ul> <?php else: ?> <p>No results.</p> <?php endif; ?>
The view cache manager nows accept params in factories.yml. Generating the
cache key for a view has been refactored in different methods to ease
extending the class.
Two params are available in factories.yml:
cache_key_use_vary_headers (default: true): specify if the cache keys
should include the vary headers part. In practice, it says if the page
cache should be http header dependent, as specified in vary cache
parameter.
cache_key_use_host_name (default: true): specify if the cache keys
should include the host name part. In practice, it says if page cache
should be hostname dependent.
The view cache manager no longer refuses to cache based on whether there are
values in the $_GET or $_POST arrays. The logic now simply confirms the
current request is of the GET method before checking cache.yml. This means
the following pages are now cacheable:
/js/my_compiled_javascript.js?cachebuster123/users?page=3getContent()The content of the request is now accessible via the getContent() method.
PUT and DELETE parametersWhen a request comes in with either a PUT or a DELETE HTTP method with a
content type set to application/x-www-form-urlencoded, symfony now parses
the raw body and makes the parameters accessible like normal POST parameters.
redirect()The sfAction::redirect() method family is now compatible with the url_for()
signature introduced in symfony 1.2:
// symfony 1.2 $this->redirect(array('sf_route' => 'article_show', 'sf_subject' => $article)); // symfony 1.3/1.4 $this->redirect('article_show', $article);
This enhancement was also applied to redirectIf() and redirectUnless().
link_to_if(), link_to_unless()The link_to_if() and link_to_unless() helpers are now compatible with the
link_to() signature introduced in symfony 1.2:
// symfony 1.2 <?php echo link_to_unless($foo, '@article_show?id='.$article->getId()) ?> // symfony 1.3/1.4 <?php echo link_to_unless($foo, 'article_show', $article) ?>
You can now listen to context.method_not_found to dynamically add methods to
sfContext. This is useful if you are added a lazy-loading factory, perhaps
from a plugin.
class myContextListener { protected $factory = null; public function listenForMethodNotFound(sfEvent $event) { $context = $event->getSubject(); if ('getLazyLoadingFactory' == $event['method']) { if (null === $this->factory) { $this->factory = new myLazyLoadingFactory($context->getEventDispatcher()); } $event->setReturnValue($this->factory); return true; } } }
If you find a typo or an error, please register and open a ticket.
If you need support or have a technical question, please post to the official user mailing-list.
