<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3825636150904136311</id><updated>2012-02-13T00:17:52.579+01:00</updated><category term='mail'/><category term='tools'/><category term='docs'/><category term='SQL'/><category term='python'/><category term='task'/><category term='behavior'/><category term='modelling'/><category term='AJAX'/><category term='design'/><category term='diagrams'/><category term='hosting'/><category term='event'/><category term='symfony'/><category term='plugins'/><category term='filter'/><category term='svn'/><category term='form'/><title type='text'>Symfony world</title><subtitle type='html'>tips n'tricks for web developers</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>49</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4773932732632339989</id><published>2012-02-13T00:17:00.003+01:00</published><updated>2012-02-13T00:17:52.587+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='modelling'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='docs'/><category scheme='http://www.blogger.com/atom/ns#' term='diagrams'/><title type='text'>excellent modelling tool: cacoo</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Gw-WFcKaIvU/Tzg088eRrSI/AAAAAAAAGwA/gHOnt-hh0k4/s1600/diagrams.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Gw-WFcKaIvU/Tzg088eRrSI/AAAAAAAAGwA/gHOnt-hh0k4/s576/diagrams.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from the epic "Braveheart" by Mel Gibson (1995)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;This time I want to present an excellent visual tool I've started using recently to improve my projects' documentation. It's the &lt;a href"http://cacoo.com"&gt;Cacoo&lt;/a&gt; online diagram editor, which is a professional flash tool.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-uXyFWmo_cRA/TzhANjukbGI/AAAAAAAAGw8/0zZ22aoojFU/s1600/cacoo.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="89" width="265" src="http://1.bp.blogspot.com/-uXyFWmo_cRA/TzhANjukbGI/AAAAAAAAGw8/0zZ22aoojFU/s400/cacoo.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;The basic concept is very easy: &lt;b&gt;you create graphic diagrams&lt;/b&gt;. You may structure them in folders and sheets (don't worry, each country should have its own translation already - I'm using Polish version):&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-HF19dQqHR0U/TzhEP_4AT5I/AAAAAAAAGz8/9fTLu4Bo0JY/s1600/diagram2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="400" src="http://2.bp.blogspot.com/-HF19dQqHR0U/TzhEP_4AT5I/AAAAAAAAGz8/9fTLu4Bo0JY/s400/diagram2.png" /&gt;&lt;/a&gt;&lt;/div&gt;There's a history of all changes done on each diagram:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uJtTHYcWT3s/TzhEM-PGYHI/AAAAAAAAGzw/KB4Mhs9bHbk/s1600/diagram1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="250" width="400" src="http://4.bp.blogspot.com/-uJtTHYcWT3s/TzhEM-PGYHI/AAAAAAAAGzw/KB4Mhs9bHbk/s400/diagram1.png" /&gt;&lt;/a&gt;&lt;/div&gt;Creating a diagram usually starts with creating your own, custom objects which represent something. You may use standard, predefined objects or import any image from the internet to combine new objects:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-cECXiRXISSs/TzhDDecYsCI/AAAAAAAAGyo/PKC3mwKFwh0/s1600/diagrams3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="160" width="236" src="http://4.bp.blogspot.com/-cECXiRXISSs/TzhDDecYsCI/AAAAAAAAGyo/PKC3mwKFwh0/s400/diagrams3.png" /&gt;&lt;/a&gt;&lt;/div&gt;You may resize or change the angle of an object:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-RR3P3GDbIF0/TzhDGk6075I/AAAAAAAAGy0/WqP-3VSNV04/s1600/diagram4.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="256" width="313" src="http://1.bp.blogspot.com/-RR3P3GDbIF0/TzhDGk6075I/AAAAAAAAGy0/WqP-3VSNV04/s400/diagram4.png" /&gt;&lt;/a&gt;&lt;/div&gt;There are lots of predefined stencils to USE, including entire UML:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-lpkGXtmno0A/TzhDKEfOc4I/AAAAAAAAGzA/A68JDHuojvM/s1600/diagrams5.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="400" width="302" src="http://1.bp.blogspot.com/-lpkGXtmno0A/TzhDKEfOc4I/AAAAAAAAGzA/A68JDHuojvM/s400/diagrams5.png" /&gt;&lt;/a&gt;&lt;/div&gt;The interface is very intuitive - it took me only an hour to learn how to make the most out of cacoo.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-KGax_TVVXWw/TzhDqjREApI/AAAAAAAAGzM/JWXuabEOh_k/s1600/diagrams6.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="246" width="400" src="http://1.bp.blogspot.com/-KGax_TVVXWw/TzhDqjREApI/AAAAAAAAGzM/JWXuabEOh_k/s400/diagrams6.png" /&gt;&lt;/a&gt;&lt;/div&gt;There are dozens of easy tools you can use to make really good quality diagrams:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-8ndeDs_pPKM/TzhDvOv3sTI/AAAAAAAAGzY/3fbcpLdPxac/s1600/diagrams8.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="250" width="400" src="http://2.bp.blogspot.com/-8ndeDs_pPKM/TzhDvOv3sTI/AAAAAAAAGzY/3fbcpLdPxac/s400/diagrams8.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;I won't try to list al those tools, I hope the screenshots I made speak for themselves (especially I like the drag n'drop stuff and moving objects across the diagram).&lt;a href="http://2.bp.blogspot.com/-g3OYX3wxsDM/TzhDy5i0KMI/AAAAAAAAGzk/kYqt7-tOX8Y/s1600/diagrams9.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="357" width="342" src="http://2.bp.blogspot.com/-g3OYX3wxsDM/TzhDy5i0KMI/AAAAAAAAGzk/kYqt7-tOX8Y/s400/diagrams9.png" /&gt;&lt;/a&gt;&lt;/div&gt;And the most comfortable and user-friendy thing is easy diagram update. If your IT project has changed and your documentatin is not up to date anymore - just log in, make a tiny change in the diagram and dump it again, replace the old diagram in the docs and you're done!&lt;/p&gt;&lt;h2&gt;predefined objects to use&lt;/h2&gt;&lt;p&gt;Just get a predefined stencil - just like a nice looking professor below:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-sCNs-Aaqet0/Tzg6HVhc70I/AAAAAAAAGwM/Y-fpswQzIms/s1600/grand1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="152" width="270" src="http://4.bp.blogspot.com/-sCNs-Aaqet0/Tzg6HVhc70I/AAAAAAAAGwM/Y-fpswQzIms/s400/grand1.png" /&gt;&lt;/a&gt;&lt;/div&gt;This stencil is a group of smaller objects. You can choose some objects to be grouped to make moving easier. You can even resize a whole group of objects, including font size changes! And groups can consist of groups...&lt;/p&gt;&lt;p&gt;Anyway, a group member can still be edited separately:&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-raXuY7rAQyA/Tzg6NHK_DDI/AAAAAAAAGwY/BETjqY7hvJQ/s1600/grand2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="153" width="290" src="http://2.bp.blogspot.com/-raXuY7rAQyA/Tzg6NHK_DDI/AAAAAAAAGwY/BETjqY7hvJQ/s400/grand2.png" /&gt;&lt;/a&gt;&lt;/div&gt;There are really lots and lots of possibilities there. You can do whatever you can think of.&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-gPxA5Cz40LI/Tzg6QSqL78I/AAAAAAAAGwk/eW-o8kpYcEk/s1600/grand3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="176" width="275" src="http://3.bp.blogspot.com/-gPxA5Cz40LI/Tzg6QSqL78I/AAAAAAAAGwk/eW-o8kpYcEk/s400/grand3.png" /&gt;&lt;/a&gt;&lt;/div&gt;Finally, you can export your work to few file formats (I use ksnapshot - PNG file is enough for me).&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ZzQEtdreQdQ/Tzg8EXA3xCI/AAAAAAAAGww/IB5-caRh37c/s1600/diagrams10.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-ZzQEtdreQdQ/Tzg8EXA3xCI/AAAAAAAAGww/IB5-caRh37c/s500/diagrams10.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;h2&gt;try the demo version&lt;/h2&gt;&lt;p&gt;The &lt;i&gt;free plan&lt;/i&gt; gives you the possibility to hold 25 diagrams and it's enough to create useful diagrams, documenting your projects. I did - and I'm satisfied. Just take a look:&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-nHH6dbTITZ4/TzhATaejJ2I/AAAAAAAAGxI/gEFNql-DweY/s1600/example1.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="332" width="155" src="http://3.bp.blogspot.com/-nHH6dbTITZ4/TzhATaejJ2I/AAAAAAAAGxI/gEFNql-DweY/s400/example1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-_GhRfGZwmeQ/TzhAXbFIDmI/AAAAAAAAGxU/cVBOTDDEDDk/s1600/example2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="210" width="400" src="http://4.bp.blogspot.com/-_GhRfGZwmeQ/TzhAXbFIDmI/AAAAAAAAGxU/cVBOTDDEDDk/s400/example2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-2Do8V4xGikQ/TzhCa9NH_XI/AAAAAAAAGxg/P8d4IGry8xY/s1600/example3.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="308" width="400" src="http://1.bp.blogspot.com/-2Do8V4xGikQ/TzhCa9NH_XI/AAAAAAAAGxg/P8d4IGry8xY/s400/example3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-wQ_0ihjVx4A/TzhCeTDLnpI/AAAAAAAAGxs/xXTpXfzg8bY/s1600/example4.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="236" width="400" src="http://3.bp.blogspot.com/-wQ_0ihjVx4A/TzhCeTDLnpI/AAAAAAAAGxs/xXTpXfzg8bY/s400/example4.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-AsG2Zr5Q8cQ/TzhChxikdII/AAAAAAAAGx4/c0Vg0Dc2TVw/s1600/example5.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="232" width="400" src="http://2.bp.blogspot.com/-AsG2Zr5Q8cQ/TzhChxikdII/AAAAAAAAGx4/c0Vg0Dc2TVw/s400/example5.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-yHzlp4JCTZw/TzhCl59ohUI/AAAAAAAAGyE/MlNh4ICUp2o/s1600/example6.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="262" width="400" src="http://2.bp.blogspot.com/-yHzlp4JCTZw/TzhCl59ohUI/AAAAAAAAGyE/MlNh4ICUp2o/s400/example6.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;they didn't found me - I found them :)&lt;/h2&gt;&lt;p&gt;Just to make it clear - &lt;b&gt;I was not contacted by the &lt;a href="http://cacoo.com"&gt;Cacoo&lt;/a&gt; team&lt;/b&gt; and I was not asked if I could write a nice review (things like this happen - some time ago I was asked to review a pro-symfony IDE) ;-). So there was no bribe. One day I was just looking for a free UML-designing software (desktop app or online), because I was finding StarUML less and less satisfying. I found Cacoo and I didn't need to search any longer.&lt;/p&gt;&lt;p&gt;&lt;a href="http://cacoo.com"&gt;Try it&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4773932732632339989?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4773932732632339989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/02/excellent-modelling-tool-cacoo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4773932732632339989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4773932732632339989'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/02/excellent-modelling-tool-cacoo.html' title='excellent modelling tool: cacoo'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-Gw-WFcKaIvU/Tzg088eRrSI/AAAAAAAAGwA/gHOnt-hh0k4/s72-c/diagrams.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7154506259371963413</id><published>2012-02-05T18:48:00.000+01:00</published><updated>2012-02-10T18:16:31.293+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>svn blame: who made the bug?</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-INvntT0l2Qg/TzTuU1bjrPI/AAAAAAAAGqI/SVZthu-KORE/s1600/svn_blame.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-INvntT0l2Qg/TzTuU1bjrPI/AAAAAAAAGqI/SVZthu-KORE/s576/svn_blame.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "12 Angry Men" by Sidney Lumet (1957)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;In bigger projects it happens quite often that an unknown team member has made a modification that caused a lot of trouble. And no one wants to confess... It is quite uncomfortable to analyse distinct revisions and changes of a file to find who caused the problem, as it is time consuming. This is where &lt;a href="http://www.linxit.de/svnbook/en/1.0/re02.html"&gt;svn blame&lt;/a&gt; is the perfect tool - you execute it upon a chosen target to display revision number, team member and content line by line. You can easily find who is the author of a bug and when he committed it. It's intereting, that despite being very useful, this tool is not very known.&lt;/p&gt;&lt;h2&gt;blame me if you can find me quickly!&lt;/h2&gt;&lt;p&gt;The usage is very simple:&lt;pre&gt;&lt;br /&gt;tducin@workshop:/var/www/admin/config/doctrine$ svn blame schema.yml&lt;br /&gt;&lt;/pre&gt;and you have the entire file analysed:&lt;pre&gt;&lt;br /&gt;   367     dennis connection: master&lt;br /&gt;   362     tducin&lt;br /&gt;   362     tducin options:&lt;br /&gt;   362     tducin   charset: utf8&lt;br /&gt;   362     tducin   collate: utf8_general_ci&lt;br /&gt;   362     tducin&lt;br /&gt;  3755     george Status:&lt;br /&gt;  3755     george   comment: "Statusy"&lt;br /&gt;   491     dennis   actAs:&lt;br /&gt;  1980     dennis     SoftDelete: ~&lt;br /&gt;  1793     harold     Timestampable: ~&lt;br /&gt;  1793     harold     Signable: ~&lt;br /&gt;   492     tducin   columns:&lt;br /&gt;   492     tducin     name:&lt;br /&gt;  3755     george       type: string(64)&lt;br /&gt;   492     tducin       notnull: true&lt;br /&gt;  2628     tducin       comment: "nazwa"&lt;br /&gt;  3755     george     notify_mail:&lt;br /&gt;  3755     george       type: boolean&lt;br /&gt;  3755     george       notnull: true&lt;br /&gt;  3755     george       default: false&lt;br /&gt;  3755     george       comment: "klient ma być powiadamiany mailowo"&lt;br /&gt;  1541     dennis     stock_mode:&lt;br /&gt;  1541     dennis       type: enum&lt;br /&gt;  1541     dennis       values: [ reserved, sent, cancelled ]&lt;br /&gt;  1541     dennis       default: reserved&lt;br /&gt;  2628     dennis       comment: "tryb magazynowy: reserved, sent, cancelled"&lt;br /&gt;  3755     george     force_reminder:&lt;br /&gt;   892     tducin       type: boolean&lt;br /&gt;   878     tducin       notnull: true&lt;br /&gt;  3755     george       comment: "Wymuszenie dodania wpisu w kalendarzu"&lt;br /&gt;  3755     george     block_update:&lt;br /&gt;  3755     george       type: boolean&lt;br /&gt;  3755     george       notnull: true&lt;br /&gt;  3755     george       comment: "Blokada zmiany statusu"&lt;br /&gt;  4078     harold   indexes:&lt;br /&gt;  4078     harold     softdelete_idx:&lt;br /&gt;  4078     harold       fields: [ deleted_at ]&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7154506259371963413?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7154506259371963413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/02/svn-blame-who-made-bug.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7154506259371963413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7154506259371963413'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/02/svn-blame-who-made-bug.html' title='svn blame: who made the bug?'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-INvntT0l2Qg/TzTuU1bjrPI/AAAAAAAAGqI/SVZthu-KORE/s72-c/svn_blame.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-5092377280099549633</id><published>2012-01-29T17:06:00.000+01:00</published><updated>2012-01-29T17:06:53.110+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='filter'/><title type='text'>symfony range filter</title><content type='html'>&lt;p&gt;In symfony/doctrine, only the &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors/en#core-behaviors:timestampable"&gt;Timestampable behavior&lt;/a&gt; provides ranged filters (a combination of &lt;strong&gt;from&lt;/strong&gt; and &lt;strong&gt;to&lt;/strong&gt; values that are queried just like &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between"&gt;MySQL BETWEEN statement&lt;/a&gt;). But how about ranged values for other data types?&lt;/p&gt;&lt;p&gt;I thought it'd be both cool and very useful, so I set off to search the web, but found no solution. Hence, I've made one myself. We will create three new classes and modify two more files to make it work in the basic version.&lt;/p&gt;&lt;h2&gt;new widget/validator classes&lt;/h2&gt;&lt;p&gt;The first class to be added is the form widget, &lt;strong&gt;lib/widget/sfWidgetFormInputRange.class.php&lt;/strong&gt;:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; sfWidgetFormInputRange &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; sfWidgetForm&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$options&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addRequiredOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addRequiredOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'template'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'from %from_value% to %to_value%'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Renders the widget.&lt;br /&gt;   *&lt;br /&gt;   * @param  string $name        The element name&lt;br /&gt;   * @param  string $value       The value displayed in this widget&lt;br /&gt;   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes&lt;br /&gt;   * @param  array  $errors      An array of errors for the field&lt;br /&gt;   *&lt;br /&gt;   * @return string An HTML tag string&lt;br /&gt;   *&lt;br /&gt;   * @see sfWidgetForm&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; render&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$errors&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array_merge"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_merge&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/is_array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;is_array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/strtr"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;strtr&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;translate&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'template'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'%from_value%'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;render&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'[from]'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'%to_value%'&lt;/span&gt;   &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;render&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'[to]'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Gets the stylesheet paths associated with the widget.&lt;br /&gt;   *&lt;br /&gt;   * @return array An array of stylesheet paths&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getStylesheets&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/array_unique"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_unique&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array_merge"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_merge&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getStylesheets&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getStylesheets&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Gets the JavaScript paths associated with the widget.&lt;br /&gt;   *&lt;br /&gt;   * @return array An array of JavaScript paths&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getJavaScripts&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/array_unique"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_unique&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array_merge"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_merge&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getJavaScripts&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getJavaScripts&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;The second one is the form filter widget, &lt;strong&gt;lib/widget/sfWidgetFormFilterInputRange.class.php&lt;/strong&gt;:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; sfWidgetFormFilterInputRange &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; sfWidgetFormInputRange&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Configures the current widget.&lt;br /&gt;   *&lt;br /&gt;   * Available options:&lt;br /&gt;   *&lt;br /&gt;   *  * with_empty:      Whether to add the empty checkbox (true by default)&lt;br /&gt;   *  * empty_label:     The label to use when using an empty checkbox&lt;br /&gt;   *  * template:        The template used for from value and to value&lt;br /&gt;   *                     Available placeholders: %from_value%, %to_value%&lt;br /&gt;   *  * filter_template: The template to use to render the widget&lt;br /&gt;   *                     Available placeholders: %value_range%, %empty_checkbox%, %empty_label%&lt;br /&gt;   *&lt;br /&gt;   * @param array $options     An array of options&lt;br /&gt;   * @param array $attributes  An array of default HTML attributes&lt;br /&gt;   *&lt;br /&gt;   * @see sfWidgetForm&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$options&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;configure&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$options&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'with_empty'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'empty_label'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'is empty'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'template'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'from %from_value%&amp;lt;br /&amp;gt;to %to_value%'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'filter_template'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'%value_range%&amp;lt;br /&amp;gt;%empty_checkbox% %empty_label%'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Renders the widget.&lt;br /&gt;   *&lt;br /&gt;   * @param  string $name        The element name&lt;br /&gt;   * @param  string $value       The value displayed in this widget&lt;br /&gt;   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes&lt;br /&gt;   * @param  array  $errors      An array of errors for the field&lt;br /&gt;   *&lt;br /&gt;   * @return string An HTML tag string&lt;br /&gt;   *&lt;br /&gt;   * @see sfWidgetForm&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; render&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$errors&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array_merge"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array_merge&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'is_empty'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/is_array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;is_array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;a href="http://www.php.net/strtr"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;strtr&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'filter_template'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'%value_range%'&lt;/span&gt;     &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;render&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$attributes&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$errors&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'%empty_checkbox%'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'with_empty'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderTag&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'input'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'type'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'checkbox'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'name'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'[is_empty]'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'checked'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'is_empty'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; ? &lt;span style="color: rgb(0, 0, 255);"&gt;'checked'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'%empty_label%'&lt;/span&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'with_empty'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderContentTag&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'label'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;translate&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'empty_label'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'for'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;generateId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$name&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'[is_empty]'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;''&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;Finally, the last class is the widget validator, &lt;strong&gt;lib/validator/sfValidatorInputRange.class.php&lt;/strong&gt;:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; sfValidatorInputRange &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; sfValidatorBase&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Configures the current validator.&lt;br /&gt;   *&lt;br /&gt;   * Available options:&lt;br /&gt;   *&lt;br /&gt;   *  * from_value:   The from value validator (required)&lt;br /&gt;   *  * to_value:     The to value validator (required)&lt;br /&gt;   *  * from_field:  The name of the "from" value field (optional, default: from)&lt;br /&gt;   *  * to_field:    The name of the "to" value field (optional, default: to)&lt;br /&gt;   *&lt;br /&gt;   * @param array $options    An array of options&lt;br /&gt;   * @param array $messages   An array of error messages&lt;br /&gt;   *&lt;br /&gt;   * @see sfValidatorBase&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$options&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$messages&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setMessage&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'invalid'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'The begin value must be before the end value.'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addRequiredOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addRequiredOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_field'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;addOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_field'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * @see sfValidatorBase&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; doClean&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_field'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;   &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_field'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;clean&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;   &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOption&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;clean&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; ? &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;null&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$v&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorSchemaCompare&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; sfValidatorSchemaCompare&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;LESS_THAN_EQUAL&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'throw_global_error'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'invalid'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'invalid'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$v&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;clean&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$fromField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$toField&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;accustoming solution to a example project&lt;/h2&gt;For the purposes of this article, let's say we have an Offer model. We will add the offer.recommendations integer value filter in the offer admin module. The &lt;strong&gt;lib/filter/doctrine/OfferFormFilter.class.php&lt;/strong&gt; shall be improved as below:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; OfferFormFilter &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; BaseOfferFormFilter&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;configure&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setWidget&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'recommendations_range'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormFilterInputRange&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInput&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInput&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'with_empty'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setValidator&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'recommendations_range'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorInputRange&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'from_value'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorSchemaFilter&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorNumber&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'to_value'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorSchemaFilter&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'text'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorNumber&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; addRecommendationsRangeColumnQuery&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$field&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$rootAlias&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getRootAlias&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$rootAlias&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;".recommendations &amp;gt;= ?"&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'from'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/isset"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;isset&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$rootAlias&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;".recommendations &amp;lt;= ?"&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'to'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;Finally, add the filter inside the &lt;strong&gt;generator.yml&lt;/strong&gt; file of the offer module:&lt;pre class="yaml" style="font-family: monospace;"&gt;  config:&lt;br /&gt;    fields:&lt;br /&gt;      recommendations_range:&lt;br /&gt;        label: Liczba poleceń        &lt;br /&gt;    filter:&lt;br /&gt;      display: [ ..., recommendations_range]&lt;/pre&gt;&lt;/p&gt;&lt;h2&gt;result&lt;/h2&gt;&lt;p&gt;Now you can use ranged filters anywhere in your project. Moreover, you can modify this mechanism to accustom it to your project needs.&lt;/p&gt;&lt;img src="http://img11.imageshack.us/img11/9954/filterr.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-5092377280099549633?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/5092377280099549633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/01/symfony-range-filter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5092377280099549633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5092377280099549633'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/01/symfony-range-filter.html' title='symfony range filter'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7583718728588904657</id><published>2012-01-23T10:28:00.000+01:00</published><updated>2012-02-10T20:08:19.564+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony forward through LAN</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-v9iH1g9GlT8/TzVqs-COViI/AAAAAAAAGtY/ryS8MxAbRrA/s1600/forward.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-v9iH1g9GlT8/TzVqs-COViI/AAAAAAAAGtY/ryS8MxAbRrA/s576/forward.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Disney's Adventures of the Gummi Bears" by Jymn Magon &amp; Art Vitello (introduced in 1985)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Ever thought of creating an action that would run different code depending on whether the client machine is inside or outside the LAN? It's really easy yet useful. I used it few times in one of my backend apps so far. For people outside the LAN, both links are hidden (use comparison below) and the redirected links are inaccessible. Thanks to it, company employees working from outside the office may not see inaccessible links.Below is the auxiliary method:&lt;pre class="php" style="font-family: monospace;"&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Checks if the client computer is inside the LAN with a&lt;br /&gt;   * specific address. If so, redirects to a local address.&lt;br /&gt;   *&lt;br /&gt;   * @param String $ip - IP of the webpage to be forwarded to&lt;br /&gt;   * @param String $port - port of the webpage to be forwarded to&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; forwardThroughLan&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$ip&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$port&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$_SERVER&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'REMOTE_ADDR'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;==&lt;/span&gt; sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;get&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'path_server_ip'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;redirect&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'http://'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$ip&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;':'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$port&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;else&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setTemplate&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'forwardThroughLanError'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;and here is direct usage:&lt;pre class="php" style="font-family: monospace;"&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Executes forward TRAC through LAN action. Forwards to TRAC webpage&lt;br /&gt;   * inside LAN in the office building.&lt;br /&gt;   *&lt;br /&gt;   * @param sfWebRequest $request&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeForwardTracThroughLan&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;forwardThroughLan&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'192.168.1.99'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'8080'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7583718728588904657?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7583718728588904657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/01/symfony-forward-through-lan.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7583718728588904657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7583718728588904657'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/01/symfony-forward-through-lan.html' title='symfony forward through LAN'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-v9iH1g9GlT8/TzVqs-COViI/AAAAAAAAGtY/ryS8MxAbRrA/s72-c/forward.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4338016318301372333</id><published>2012-01-16T19:08:00.000+01:00</published><updated>2012-02-10T18:17:11.316+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>SVN repository auto update</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LSzsAz1DXx8/TzTyMf0c_OI/AAAAAAAAGqg/GjeHj4FIxbI/s1600/svn_auto_update.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-LSzsAz1DXx8/TzTyMf0c_OI/AAAAAAAAGqg/GjeHj4FIxbI/s576/svn_auto_update.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Brazil" by Terry Gilliam (1985)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;I found an &lt;a href="http://tech.cynarski.pl/2009/06/03/svn-hooks-i-autoupdatey/"&gt;article (in Polish)&lt;/a&gt; describing a subversion hook that will automatically update a server working copy. This seems perfect - after commiting a new revision, all changes are available online (entire development team can test the most up to date version, your boss may see the newest results, etc).&lt;/p&gt;&lt;p&gt;Anyway, I don't see any reason to use C here, so I've made my own version updating the repository using shell command:&lt;pre class="sh" style="font-family: monospace;"&gt;svn up /home/website/domains/dev.website.com/website&lt;br /&gt;  --no-auth-cache --username user --password pass&lt;/pre&gt;The --no-auth-cache option is important here - authorization data is not going to be remembered here. Other two options define the authorization data.&lt;/p&gt;&lt;h2&gt;troubleshooting&lt;/h2&gt;&lt;p&gt;You may have problems with file permissions, if the user which holds the repository is different than the user which hold the working copy (this was in my case). The problem I got was permission denied for .../.svn/lock file, which is a temporary file, existing only when the revision is being checked/committed. Oops... There is no one good solution for this - it depends on the server configuration. It can be adding one user to the group of another, changing the owner of the entire working copy files (no matter in which /home subdirectory it is, as long as web server can handle requests, etc).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4338016318301372333?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4338016318301372333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/01/svn-repository-auto-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4338016318301372333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4338016318301372333'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/01/svn-repository-auto-update.html' title='SVN repository auto update'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-LSzsAz1DXx8/TzTyMf0c_OI/AAAAAAAAGqg/GjeHj4FIxbI/s72-c/svn_auto_update.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-6031631945718800262</id><published>2012-01-15T23:40:00.000+01:00</published><updated>2012-02-10T18:17:46.530+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>force to log message SVN python</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-vjZ4412jwRs/TzT4J184iRI/AAAAAAAAGqs/wwsgKdJYY3Q/s1600/svn_force_log.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-vjZ4412jwRs/TzT4J184iRI/AAAAAAAAGqs/wwsgKdJYY3Q/s576/svn_force_log.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "It Happened One Night" by Frank Capra (1934)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Another blog post about Subversion. Few days ago someone asked me if I know how to block commiting a subversion revision that has no log message defined. I didn't, but I thought it's a good idea, because it could help to track bugs, changes, etc. There's no such configuration, but it can be achieved using &lt;a href="http://svnbook.red-bean.com/en/1.0/svn-book.html#svn-ch-5-sect-2.1"&gt;SVN hooks&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;tried to do this in PHP...&lt;/h2&gt;&lt;p&gt;There are many resources in the web giving examples to do this using a windows batch file - but I'm a linux user. At first, I wanted to do this in PHP. Although my final solution is not PHP, maybe someone will find following code snippets useful.&lt;/p&gt;&lt;p&gt;So I started searching through many pages on the web to find PHP shell scripts that could block committing a revision with no log message. The first step is, of course, to create an executable &lt;strong&gt;pre-commit&lt;/strong&gt; file in the &lt;strong&gt;hooks&lt;/strong&gt; directory of the repository. Then make the shell use the PHP parser to execute our script. Next, define path to svnlook binary and execute it:&lt;pre class="php" style="font-family: monospace;"&gt;#!/usr/local/bin/php -q&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$SVNLOOK&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'/usr/bin/svnlook'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.php.net/exec"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;exec&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;"&lt;span style="color: rgb(0, 102, 153); font-weight: bold;"&gt;$SVNLOOK&lt;/span&gt; log -t &lt;span style="color: rgb(0, 102, 153); font-weight: bold;"&gt;{$argv[2]}&lt;/span&gt; &lt;span style="color: rgb(0, 102, 153); font-weight: bold;"&gt;{$argv[1]}&lt;/span&gt;"&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$output&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$result&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;We have the output and the result of the command available. So we may just check if the message (which revision a user is just trying to commit) is empty (I guess there is no other way than to use &lt;code&gt;&lt;a href="http://www.linxit.de/svnbook/en/1.0/re51.html"&gt;svnlook&lt;/a&gt;&lt;/code&gt;). If the log message is empty, the revision shall be stopped - and this happens, when exit status code is different than 0 (of course, a message explaining the cause is appreciated):&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/empty"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;empty&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$result&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/fwrite"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;fwrite&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;STDERR&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;"Commit blocked, need to pass the log message."&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/exit"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;exit&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;else&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/exit"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;exit&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;This all should work, but 99,9% of all servers will have the exec function disabled by default (in both CLI and web server PHP configuration; along with other system functions):&lt;pre class="sh" style="font-family: monospace;"&gt;disable_functions = exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,dl,popen,show_source&lt;/pre&gt;Even if you manage to remove those functions from the configuration, you lower the server security, which may risk dangerous &lt;a href="http://en.wikipedia.org/wiki/Code_injection"&gt;script injection&lt;/a&gt;. So I forgot about using PHP...&lt;/p&gt;&lt;h2&gt;...and finally moved to python&lt;/h2&gt;&lt;p&gt;Finally, I managed to succeed using python:&lt;pre class="python" style="font-family: monospace;"&gt;&lt;span style="color: rgb(128, 128, 128); font-style: italic;"&gt;#!/usr/bin/python&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;import&lt;/span&gt; &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;, &lt;span style="color: rgb(220, 20, 60);"&gt;os&lt;/span&gt;, &lt;span style="color: rgb(220, 20, 60);"&gt;string&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;SVNLOOK=&lt;span style="color: rgb(72, 61, 139);"&gt;'/usr/bin/svnlook'&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;def&lt;/span&gt; main&lt;span style="color: black;"&gt;(&lt;/span&gt;repos, txn&lt;span style="color: black;"&gt;)&lt;/span&gt;:&lt;br /&gt;  log_cmd = &lt;span style="color: rgb(72, 61, 139);"&gt;'%s log -t "%s" "%s"'&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;%&lt;/span&gt; &lt;span style="color: black;"&gt;(&lt;/span&gt;SVNLOOK, txn, repos&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;  log_msg = &lt;span style="color: rgb(220, 20, 60);"&gt;os&lt;/span&gt;.&lt;span style="color: black;"&gt;popen&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;log_cmd, &lt;span style="color: rgb(72, 61, 139);"&gt;'r'&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;.&lt;span style="color: rgb(220, 20, 60);"&gt;readline&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;.&lt;span style="color: black;"&gt;rstrip&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(72, 61, 139);"&gt;'n'&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;len&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;log_msg&lt;span style="color: black;"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: rgb(255, 69, 0);"&gt;10&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;stderr&lt;/span&gt;.&lt;span style="color: black;"&gt;write&lt;/span&gt; &lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(72, 61, 139);"&gt;"&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;\n&lt;/span&gt;&amp;gt; Revision comment must be defined&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;\n&lt;/span&gt;"&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;exit&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 69, 0);"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;else&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;exit&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 69, 0);"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;if&lt;/span&gt; __name__ == &lt;span style="color: rgb(72, 61, 139);"&gt;'__main__'&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;len&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;argv&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: rgb(255, 69, 0);"&gt;3&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;stderr&lt;/span&gt;.&lt;span style="color: black;"&gt;write&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(72, 61, 139);"&gt;"&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;\n&lt;/span&gt;&amp;gt; Usage: %s REPOS TXN&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;\n&lt;/span&gt;"&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;%&lt;/span&gt; &lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;argv&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: rgb(255, 69, 0);"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 119, 0); font-weight: bold;"&gt;else&lt;/span&gt;:&lt;br /&gt;    main&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;argv&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: rgb(255, 69, 0);"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;, &lt;span style="color: rgb(220, 20, 60);"&gt;sys&lt;/span&gt;.&lt;span style="color: black;"&gt;argv&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: rgb(255, 69, 0);"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-6031631945718800262?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/6031631945718800262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2012/01/force-to-log-message-svn-python.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6031631945718800262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6031631945718800262'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2012/01/force-to-log-message-svn-python.html' title='force to log message SVN python'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-vjZ4412jwRs/TzT4J184iRI/AAAAAAAAGqs/wwsgKdJYY3Q/s72-c/svn_force_log.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-3314215022435452707</id><published>2011-12-15T23:07:00.000+01:00</published><updated>2012-02-10T18:18:56.361+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>svnsync tutorial</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-MONJlEJju10/TzT6-8d9rfI/AAAAAAAAGq4/YxZ00zBi1V0/s1600/svn_sync.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-MONJlEJju10/TzT6-8d9rfI/AAAAAAAAGq4/YxZ00zBi1V0/s576/svn_sync.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from magnificent "One Flew Over the Cuckoo's Nest" By Miloš Forman&lt;/span&gt;&lt;/div&gt;&lt;p&gt;I was forced to use this tool when I wanted to move my old project repository into a new server (until then, its SVN repository was hosted on a free SVN hosting). The hosting provider forced me to pay for the svnadmin dump, so I searched for an alternative solution and &lt;code&gt;svnsync&lt;/code&gt; did the job.&lt;/p&gt;&lt;p&gt;In comparison to &lt;code&gt;svnadmin dump&lt;/code&gt;/&lt;code&gt;load&lt;/code&gt;, &lt;a href="http://svnbook.red-bean.com/en/1.4/svn.ref.svnsync.html"&gt;&lt;code&gt;svnsync&lt;/code&gt;&lt;/a&gt; is migrating subversion repository with no svnadmin access. The migration can be done when you have a working copy (checkout) of the source repository and a clean (&lt;code&gt;svnadmin create&lt;/code&gt;) version of the target repository. The repository synchronization is just reading all revisions one by one and copying them into the target repository, unchanged.&lt;/p&gt;&lt;p&gt;First, take a look at &lt;a href="http://www.svnsite.com/content/page/svnsync"&gt;this article&lt;/a&gt;. Here you can find that a hook needs to be created in the target repository: &lt;i&gt;hooks/pre-revprop-change&lt;/i&gt; (removing &lt;i&gt;.tmpl&lt;/i&gt; and granting executable permissions for the script). What is not mentioned in the article above is that you should probably put&lt;pre style='color:#000000;'&gt;&lt;span style='color:#696969; '&gt;#!&lt;/span&gt;&lt;span style='color:#007997; '&gt;/bin/sh&lt;/span&gt;&lt;span style='color:#bb7977; font-weight:bold; '&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style='color:#bb7977; font-weight:bold; '&gt;exit&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#800080; '&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;as the &lt;i&gt;hooks/pre-revprop-change&lt;/i&gt; script content, to avoid the error, as written in &lt;a href="http://blog.elijaa.org/index.php?post/2010/09/23/revprop-change-blocked-by-pre-revprop-change-hook-%28exit-code-255%29-with-no-output-error"&gt;another article&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Now, initialize the synchronization (example call below):&lt;/p&gt;&lt;pre style='color:#000000;'&gt;svnsync init &lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;target repository&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt; &lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;source repository&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;br /&gt;svnsync init file&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/home/user/svn/test-repo&lt;/span&gt; svn&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/free-hosting/that-forced-me-to-pay/for-the-svn-dump&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;and copy all revisions, while being in the working copy of the source repository (example call below again):&lt;/p&gt;&lt;pre style='color:#000000;'&gt;svnsync --non-interactive sync &lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;target repository&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;br /&gt;svnsync --non-interactive sync file&lt;span style='color:#808030; '&gt;:&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/&lt;/span&gt;&lt;span style='color:#70018a; '&gt;/home/user/svn/test-repo&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Be patient and wait until it's finished. Afterwards, remove the useless hooks/pre-revprop-change script - and you're done!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-3314215022435452707?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/3314215022435452707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/12/svnsync-tutorial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3314215022435452707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3314215022435452707'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/12/svnsync-tutorial.html' title='svnsync tutorial'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-MONJlEJju10/TzT6-8d9rfI/AAAAAAAAGq4/YxZ00zBi1V0/s72-c/svn_sync.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-3598263723568278781</id><published>2011-11-08T20:58:00.000+01:00</published><updated>2012-02-10T20:12:17.738+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>extending doctrine admin module: filtered sum</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-406zc_c0VE8/TzVryMJDqNI/AAAAAAAAGtk/WYUGyiwylKk/s1600/tiffany.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-406zc_c0VE8/TzVryMJDqNI/AAAAAAAAGtk/WYUGyiwylKk/s576/tiffany.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Breakfast at Tiffany's" by Blake Edwards (1961)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Another post for symfony beginners. I'll show how to display a sum (or any other function) of all elements filtered in an admin module. &lt;u&gt;All elements&lt;/u&gt; - meaning the ones displayed on the current page (list pagination) and all the rest which is not currently visible. This is going to be really easy.&lt;/p&gt;&lt;h2&gt;action&lt;/h2&gt;&lt;p&gt;Let's start with calculations. We need to get the sum of all filtered elements and pass it to the &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/07-Inside-the-View-Layer"&gt;View&lt;/a&gt;. As this article is not about &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/02-Exploring-Symfony-s-Code#chapter_02_the_mvc_pattern"&gt;MVC design pattern&lt;/a&gt;, I'll just override &lt;i&gt;executeIndex&lt;/i&gt; action and put the calculations code inside (to make it as easy as possible, though &lt;u&gt;calculations should be done in model, not controller&lt;/u&gt;).&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; xxxActions &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; autoXxxActions&lt;br /&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeIndex&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 163, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;executeIndex&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;buildQuery&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;copy&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$root_alias&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;getRootAlias&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$total_data&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;limit&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;select&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;"SUM(&lt;span style="color: rgb(0, 102, 153); font-weight: bold;"&gt;{$root_alias}&lt;/span&gt;.cash_total) AS sum"&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;fetchArray&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;total_count&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$total_data&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sum'&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 163, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;As you can see, we've got a &lt;i&gt;Xxx&lt;/i&gt; model which holds the &lt;i&gt;cash_total: decimal&lt;/i&gt; column, representing a sum of money. The &lt;i&gt;$this-&gt;buildQuery()-&gt;clone()&lt;/i&gt; part does all the magic - we have the query with all filters set by the user in the interface. We will only tell doctrine to calculate the sum of all filtered elements for us (&lt;i&gt;$total_count&lt;/i&gt; variable will be available in the &lt;i&gt;indexSuccess.php&lt;/i&gt; template). The &lt;i&gt;-&gt;limit(0)&lt;/i&gt; clears the SQL limit clause, of course.&lt;/p&gt;&lt;h2&gt;templates&lt;/h2&gt;&lt;p&gt;This part is boring, actually. We need to override two more files: &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/14-Admin-Generator#chapter_14_sub_a_look_at_the_generated_code"&gt;fetch them from cache&lt;/a&gt; and put them in the module/template directory. These files are: &lt;i&gt;indexSuccess.php&lt;/i&gt; in which the line&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'event/list'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'pager'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$pager&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'sort'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sort&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'helper'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$helper&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;should be replaced with:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'event/list'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'pager'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$pager&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'sort'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sort&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'helper'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$helper&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'total_count'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$total_count&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;and the &lt;i&gt;_list.php&lt;/i&gt; partial which should have few lines added:&lt;pre class="html4strict" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tfoot.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tfoot&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 128); font-style: italic;"&gt;&amp;lt;!-- added code starts here --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/th.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;th&lt;/span&gt;&lt;/a&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;colspan&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;"6"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      w sumie: &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; Tools&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;priceFormat&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$total_count&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 163, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/th.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;th&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(128, 128, 128); font-style: italic;"&gt;&amp;lt;!-- added code ends here --&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 163, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/th.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;th&lt;/span&gt;&lt;/a&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;colspan&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;"6"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$pager&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 80, 0);"&gt;haveToPaginate&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;         &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'event/pagination'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'pager'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$pager&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 163, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;endif&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;As you can see, it's trivial, yet useful.&lt;/p&gt;&lt;p&gt;The sum of all filtered elements is visible in the footer of the doctrine admin module list table, as you can see below, but you can put it anywhere you want (as long as it's in the index action templates):&lt;br /&gt;&lt;img src="http://img267.imageshack.us/img267/4484/sumg.png" /&gt;&lt;/p&gt;&lt;h2&gt;other functions&lt;/h2&gt;&lt;p&gt;Of course, you can use other aggregate functions, such as average, minumum or maximum element - just take a look at the &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html"&gt;MySQL documentation&lt;/a&gt;. You may also create &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/adding-functions.html"&gt;your own functions&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-3598263723568278781?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/3598263723568278781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/11/extending-doctrine-admin-filtered-sum.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3598263723568278781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3598263723568278781'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/11/extending-doctrine-admin-filtered-sum.html' title='extending doctrine admin module: filtered sum'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-406zc_c0VE8/TzVryMJDqNI/AAAAAAAAGtk/WYUGyiwylKk/s72-c/tiffany.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4647533354859075203</id><published>2011-11-06T19:10:00.000+01:00</published><updated>2012-01-15T22:22:15.447+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><title type='text'>symfony basics: form default values</title><content type='html'>&lt;p&gt;This is some stuff for symfony beginners, who still want to learn symfony 1.4. You may set default form values for all kind of &lt;a href="http://www.symfony-project.org/forms/1_4/en/"&gt;forms&lt;/a&gt; (including doctrine forms). Set one default value at a time:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; XxxForm &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; BaseXxxForm&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDefault&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'field'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'value'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;or set a whole array of them:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDefaults&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'field_1'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'value_1'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'field_2'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'value_2'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// ...&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'field_x'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'value_x'&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;h2&gt;default values for new objects&lt;/h2&gt;&lt;p&gt;Sometimes you want to set the default form values just before the object is created, because it'd be easier for the aplication user to fill in some data. For example, the owner/author of a blog post may be set default to the current logged in user - or the date of an event may be set to now - and so on. This can be achieved with the &lt;strong&gt;isNew&lt;/strong&gt; method of the doctrine form class (&lt;i&gt;lib/form/doctrine/XxxForm.class.php&lt;/i&gt;):&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;isNew&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDefault&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'created_at'&lt;sup&gt;1&lt;/sup&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/date"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;date&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Y-m-d 00:00:00'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDefault&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'created_by'&lt;sup&gt;2&lt;/sup&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; sfContext&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUser&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;sup&gt;3&lt;/sup&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;note &lt;sup&gt;1&lt;/sup&gt;: &lt;a href="http://www.doctrine-project.org/documentation/manual/1_1/pl/behaviors:core-behaviors:timestampable"&gt;Timestampable Doctrine behavior&lt;/a&gt; used in this example,&lt;/li&gt;&lt;li&gt;note &lt;sup&gt;2&lt;/sup&gt;: &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin"&gt;Signable Doctrine behavior&lt;/a&gt; used in this example,&lt;/li&gt;&lt;li&gt;note &lt;sup&gt;3&lt;/sup&gt;: check &lt;a href="http://prendreuncafe.com/blog/post/2010/02/17/User-Dependant-Forms-with-Symfony"&gt;this blog post&lt;/a&gt; to avoid using &lt;i&gt;sfContext::getInstance()&lt;/i&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;h2&gt;moreover&lt;/h2&gt;&lt;p&gt;You may implement whatever complex conditions you want your doctrine form to follow. Look at some of examples below:&lt;ul&gt;&lt;li&gt;&lt;u&gt;current time&lt;/u&gt; - &lt;a href="http://php.net/manual/en/function.time.php"&gt;php time function&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;u&gt;language/localization&lt;/u&gt; (default country when registering a new user) - use &lt;a href="http://www.w3.org/International/questions/qa-accept-lang-locales"&gt;Accept-Language HTTP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;u&gt;default settings set for a registered user&lt;/u&gt; - fetch individual user settings from database (doctrine query)&lt;/li&gt;&lt;li&gt;&lt;u&gt;last used item&lt;/u&gt; (category/product/etc.) - a user inserts or updates a large amount of data, when he choses a specific item (category/product) it can be saved in its session (&lt;i&gt;$user-&gt;set/getAttribute()&lt;/i&gt;) - when another record is processed, last used item is used as default (which, again, lowers time needed for the user to work)&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;A well designed interface includes lots of form default values&lt;/strong&gt;, so that users don't have to waste their time on picking up the same values over and over again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4647533354859075203?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4647533354859075203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/11/symfony-basics-form-default-values.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4647533354859075203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4647533354859075203'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/11/symfony-basics-form-default-values.html' title='symfony basics: form default values'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7274146300046400969</id><published>2011-10-31T23:09:00.000+01:00</published><updated>2011-12-15T22:48:43.796+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony dynamic max_per_page</title><content type='html'>&lt;h1&gt;max_per_page&lt;/h1&gt;&lt;p&gt;In this post I'll show a very easy and a really useful thing. It is dynamic &lt;i&gt;max_per_page&lt;/i&gt; value of the list pager. Such feature gives you the possibility &lt;strong&gt;to change the number of elements displayed in a list&lt;/strong&gt; just by &lt;strong&gt;one click&lt;/strong&gt;. It can be used both in the frontend and backend (the pager is the same) - I'll use the doctrine generated admin module (and the interface will be placed inside the filters box):&lt;img src="http://img577.imageshack.us/img577/3299/filters.png" alt="interface allowing backend user to change the max_per_page value in the 'filters' box" /&gt;&lt;/p&gt;&lt;h2&gt;templates&lt;/h2&gt;&lt;p&gt;First, let's make it visible. Add the following entry to application config/app.yml file:&lt;pre&gt;&lt;br /&gt;all:&lt;br /&gt;  const:&lt;br /&gt;    max_per_page: [ 10, 25, 50 ]&lt;br /&gt;&lt;/pre&gt;Now we may refer to &lt;i&gt;app_const_max_per_page&lt;/i&gt; config value which holds few standard &lt;i&gt;max_per_page&lt;/i&gt; values to be used (this can be used in many different admin modules). Let's say we've got an admin module for our custom &lt;i&gt;MyModel&lt;/i&gt; model. Now, override the cached &lt;strong&gt;_filters.php&lt;/strong&gt; template: fetch it from &lt;i&gt;cache/admin/dev/modules/autoMyModel/templates&lt;/i&gt; and put it in &lt;i&gt;apps/APP/modules/my_model/templates&lt;/i&gt;. Take a look at the following part of the code:&lt;pre class="html4strict" style="font-family: monospace;"&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tfoot.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tfoot&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tbody.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tbody&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(128, 128, 128); font-style: italic;"&gt;&amp;lt;!-- insert here --&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;colspan&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;"2"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;and insert few lines of code (replace the comment) to get the following:&lt;pre class="html4strict" style="font-family: monospace;"&gt;&lt;br /&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tfoot.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tfoot&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tbody.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tbody&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;colspan&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;"2"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            set maximum elements per page:&lt;br /&gt;            &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;get&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'app_const_max_per_page'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;              &amp;lt;span class="max_per_page_selector"&amp;gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; link_to&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'my_model/setMaxPerPage?max='&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&amp;lt;/span&amp;gt;&lt;br /&gt;            &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;endforeach&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;span style="color: rgb(102, 204, 102);"&gt;/&lt;/span&gt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/tr.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;tr&lt;/span&gt;&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style="color: rgb(0, 153, 0);"&gt;&amp;lt;&lt;a href="http://december.com/html/4/element/td.html"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;td&lt;/span&gt;&lt;/a&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;colspan&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;"2"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;h2&gt;controller/action&lt;/h2&gt;&lt;p&gt;The interface to change &lt;i&gt;max_per_page&lt;/i&gt; is ready, so we have to improve the controller now. Let's add an action which stores the number of elements to display per page in user session (symofny has nice &lt;i&gt;set(get)Attributes&lt;/i&gt; methods). So here it comes:&lt;pre class="php" style="font-family: monospace;"&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Sets my_model list's max per page config value, using user session&lt;br /&gt;   * attribute.&lt;br /&gt;   *&lt;br /&gt;   * @param sfWebRequest $request&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeSetMaxPerPage&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUser&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setAttribute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'my_model.max_per_page'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$max&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getParameter&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'max'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUser&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setFlash&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'notice'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'max_per_page has been set to: '&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$max&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;redirect&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'@my_model'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;h2&gt;configuration generator&lt;/h2&gt;&lt;p&gt;And finally, tell the pager to look for the custom value each time the list is going to be rendered. We need to override the method in configuration generator of the admin module:&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;class&lt;/span&gt; my_modelGeneratorConfiguration &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;extends&lt;/span&gt; BaseMy_modelGeneratorConfiguration&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Returns max_per_page config value for my_model module. If it's not&lt;br /&gt;   * defined manually by the user, default value is returned.&lt;br /&gt;   *&lt;br /&gt;   * @return Integer&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getPagerMaxPerPage&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$max&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; sfContext&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getInstance&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUser&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getAttribute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'my_model.max_per_page'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$max&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;else&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getPagerMaxPerPage&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;It's all as easy as it could be. The controller searches the servers for the current user session data and returns either the custom data (if found) or the default value (which is taken from the &lt;i&gt;generator.yml&lt;/i&gt; file).&lt;/p&gt;&lt;p&gt;Unfortunately, the &lt;i&gt;sfContext::getInstance()&lt;/i&gt; is used here (this causes a lot of problems when &lt;i&gt;the default context&lt;/i&gt; problem occurs). After a quick look I didn't find the better way to access the user from the configuration generator (but if you know how to - let me know ;).&lt;/p&gt;(I'm wondering why it's not built in into symfony).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7274146300046400969?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7274146300046400969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/10/symfony-dynamic-maxperpage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7274146300046400969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7274146300046400969'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/10/symfony-dynamic-maxperpage.html' title='symfony dynamic max_per_page'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-6252192582400173885</id><published>2011-08-16T07:56:00.000+02:00</published><updated>2012-01-15T22:13:19.122+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><title type='text'>doctrine act as signable plugin - new releases</title><content type='html'>&lt;p&gt;After few months, new versions 1.2.2 and 1.2.3 of &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin"&gt;sfDoctrineActAsSignablePlugin&lt;/a&gt; have been released. In short, the plugin provides a &lt;b&gt;Signable&lt;/b&gt; behavior which automatically stores information on who has created or updated a given object.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;what's new&lt;/h2&gt;&lt;p&gt;A fellow symfony developer, &lt;b&gt;Daniel Möllenbeck&lt;/b&gt;, suggested that there are some options missing in the behavior configuration. Until version 1.2.1, the &lt;i&gt;onDelete&lt;/i&gt; option was hardcoded as &lt;i&gt;CASCADE&lt;/i&gt;, which - as Daniel emphasised - may cause problems when a given user is supposed to be deleted (physically from the database, not &lt;a href="http://symfony-world.blogspot.com/2010/10/doctrine-softdelete-behavior-usage.html"&gt;softDeleted&lt;/a&gt;).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_created_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;created_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; CASCADE;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_updated_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;updated_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; CASCADE;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Let's imagine user enters customers over and over, then leaves the company. Now the admin deletes the user - probably the hard way (directly on the database, maybe the user is auto-created from somewhere...) --&gt; The constraint will trigger the deletion of all customers created by that user. I have some doubt anybody would be happy about that.&lt;br /&gt;&lt;br /&gt;Having the constraint like that does the trick:&lt;br /&gt;&lt;br /&gt;a) allow NULL values in created_by/updated_by columns:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_created_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;created_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SET&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_updated_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;updated_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SET&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;b) forbid the deletion of the user:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_created_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;created_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; RESTRICT;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT customer_updated_by_sf_guard_user_id&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;updated_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; sf_guard_user&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; RESTRICT;&lt;/pre&gt;&lt;br /&gt;c) do nothing&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;moreover&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Another fellow symfony developer, Christoph Berg, helped me to trace the bug with fixtures on created_by/updated_by values. Now, the bug is fixed and all fixture data works perfectly.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the community&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Taking the opportunity, I'd like to thank Daniel, Christoph and all other symfony developers who share their opinions on my work - they help to find bugs and suggest some good ideas on how to improve the code. Thanks to you, the plugin gets better and better all the time. Thanks, guys!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Please, feel free to share your opinion and comment on the plugin!&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-6252192582400173885?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/6252192582400173885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/08/doctrine-act-as-signable-plugin.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6252192582400173885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6252192582400173885'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/08/doctrine-act-as-signable-plugin.html' title='doctrine act as signable plugin - new releases'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-5087490774789078560</id><published>2011-08-15T18:11:00.000+02:00</published><updated>2011-12-15T22:49:02.050+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony custom configuration files</title><content type='html'>&lt;h1&gt;dynamic and cross-application configuration&lt;/h1&gt;&lt;p&gt;If your project gets very big and it has several applications, you may want to create cross-application configuration - store it in one place and let all applications use it (no matter how big it is). Or simply if your configuration is becoming really big and you want to arrange it somehow, custom config files is exactly what you are looking for!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;how to do that&lt;/h1&gt;&lt;p&gt;That's only three easy steps. First, let's create a custom configuration YAML file (&lt;strong&gt;config/something.yml&lt;/strong&gt;, in the project main directory, not the app config directory) and put some data there:&lt;br /&gt;&lt;pre&gt;prod:&lt;br /&gt;  test:  ok&lt;br /&gt;&lt;br /&gt;dev:&lt;br /&gt;  test: ko&lt;br /&gt;&lt;br /&gt;all:&lt;br /&gt;  foo:  bar&lt;br /&gt;  john: doe&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The second step is to create/update a config handler YAML file (&lt;strong&gt;config/config_handlers.yml&lt;/strong&gt;) with following example content:&lt;br /&gt;&lt;pre&gt;config/something.yml:&lt;br /&gt;  class:    sfDefineEnvironmentConfigHandler&lt;br /&gt;  param:&lt;br /&gt;    prefix: something_&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The last step is to register the configuration file in all applications you want (after this step, the configuration will be available for an application). Use the application configuration class (e.g. &lt;strong&gt;apps/frontend/config/frontendConfiguration.class.php&lt;/strong&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configure&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;....&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;require_once&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getConfigCache&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;checkConfig&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'config/something.yml'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;Now all config options defined in the new file are available in the application with the &lt;strong&gt;_something&lt;/strong&gt; prefix. The best way to check if the new file is available for the application is to run it in the &lt;i&gt;dev&lt;/i&gt; mode in the browser and check the &lt;i&gt;web debug toolbar&lt;/i&gt;, &lt;i&gt;config&lt;/i&gt; icon, &lt;i&gt;settings&lt;/i&gt; section. All configuration available for the application is displayed there. If you followed all three steps above, new file configuration should be available.&lt;br /&gt;&lt;img src="http://img846.imageshack.us/img846/5497/fsettings.png" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;&lt;a href="http://www.symfony-project.org/plugins/sfAdminDashPlugin"&gt;sfAdminDashPlugin trick&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This plugin provides an easy-to use menu divided into sections, which is configurable in YAML files. If you want to have different menus for different applications, you just have to put all configuration in the application config (by default, it's stored in &lt;a href="http://trac.symfony-project.org/browser/plugins/sfAdminDashPlugin/trunk/config/app.yml"&gt;the plugin config&lt;/a&gt;). One way is to put all menu config in the &lt;i&gt;app.yml&lt;/i&gt; file, but, as mentioned before, it can make the app.yml file grow to an enormous size, so a better solution is to create a &lt;i&gt;menu.yml&lt;/i&gt; file, which is loaded by the config handler. Everything is done the same way as before:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;create &lt;strong&gt;apps/APP/config/menu.yml&lt;/strong&gt; file and define sfAdminDash menu there&lt;/li&gt;&lt;li&gt;create or update (if exists) the config handler file (&lt;strong&gt;apps/APP/config/config_handlers.yml&lt;/strong&gt;)&lt;/li&gt;&lt;li&gt;finally, update the APP configuration class (&lt;strong&gt;apps/APP/config/APPConfiguration.class.php&lt;/strong&gt;) by registering new config file&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I hope some of you will find this flexible configuration useful :).&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-5087490774789078560?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/5087490774789078560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/08/symfony-custom-configuration-files.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5087490774789078560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5087490774789078560'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/08/symfony-custom-configuration-files.html' title='symfony custom configuration files'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-3096063531157195253</id><published>2011-06-26T22:54:00.000+02:00</published><updated>2012-01-15T22:23:29.324+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='event'/><title type='text'>Doctrine Event Listeners vs symfony fixtures</title><content type='html'>&lt;h2&gt;introduction&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;This is just an easy tip on how to use &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/16-Application-Management-Tools#chapter_16_populating_a_database"&gt;symfony fixtures&lt;/a&gt; along with &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/event-listeners/en"&gt;doctrine event listeners&lt;/a&gt; in a symfony project.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;event listeners&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Doctrine Event Listeners&lt;/strong&gt; are the methods you define to trigger an activity always after/before a Doctrine Record is created, updated, deleted, etc. These can be: &lt;i&gt;postInsert&lt;/i&gt;, &lt;i&gt;preInsert&lt;/i&gt;, &lt;i&gt;postDelete&lt;/i&gt;, &lt;i&gt;preDelete&lt;/i&gt; and so on. They can be very useful to keep the code clean and logical. A good example of usage is uploading an image and creating many different files with different sizes, representing the same image (custom thumbnails). This could be done with overriding &lt;i&gt;ImageForm&lt;/i&gt; upload mechanisms, but &lt;i&gt;postInsert&lt;/i&gt; seems more clean and easier to maintain if uploading is done using more than one symfony form class.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;fixtures&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;Fixtures&lt;/strong&gt; are a built-in symfony feature which enables you to easily populate the database with some data. It is usually test data, but for some projects, some initial data can be held in fixtures (e.g. initial configuration values). They should be used in all projects, since it's a lot easier to spot any bug using data that pretends to be real.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the problem&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The problem occurs when you combine those two features. Imagine you've got two models in your projects, A and B, related 1:1 (e.g. &lt;cite&gt;sf_guard_user&lt;/cite&gt; with &lt;cite&gt;sf_guard_user_profile&lt;/cite&gt; from &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin"&gt;sfDoctrineGuardPlugin&lt;/a&gt;). For each A record there has to exist the B record. This means, when the mother record is created (suppose A is the master model), the B record needs to be immediately created and related to A. A Doctrine Event Listener is what should be used - a A::postInsert() that creates the B record.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So far, so good - but we still want to use symfony fixtures. Let's say, we want to define 10 sample A records along 10 sample B records. So we write a fixture file with 10 A and 10 B fixtures. Next, we fire the&lt;br /&gt;&lt;pre&gt;./symfony doctrine:build --all --and-load&lt;br /&gt;&lt;/pre&gt;command and what do we find? B records are doubled! And this can be quite difficult to spot!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Each time when a A fixture is saved, the postInsert is automatically executed, therefore new B record is created. So instead of creating records in the following order: A,A,A,...(10),B,B,B,...(10), we get A,B,A,B,A,B,...(10),B,B,B,...(10), having 10 A records and 20 B records. And this is not what we wanted. Fortunately, this can be quite easily fixed.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the solution&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Just add one line to the Doctrine Event Listener:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; postInsert&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$event&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'cli'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;!=&lt;/span&gt; &lt;a href="http://www.php.net/php_sapi_name"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;php_sapi_name&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// some code here&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;We're basing on the fact, that fixtures are loaded from a &lt;strong&gt;task&lt;/strong&gt;, which uses &lt;strong&gt;command line interface (cli)&lt;/strong&gt;. Now, no fixtures use &lt;strong&gt;Doctrine Event Listeners&lt;/strong&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-3096063531157195253?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/3096063531157195253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/06/doctrine-event-listeners-vs-fixtures.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3096063531157195253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3096063531157195253'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/06/doctrine-event-listeners-vs-fixtures.html' title='Doctrine Event Listeners vs symfony fixtures'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-8797253678820255417</id><published>2011-05-08T14:54:00.000+02:00</published><updated>2012-02-10T22:10:48.447+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>data migration with symfony &amp; doctrine</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-3Nkk6wai95M/TzWHqNw2UaI/AAAAAAAAGuU/LQPHDJdF0Zc/s1600/data_migration.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-3Nkk6wai95M/TzWHqNw2UaI/AAAAAAAAGuU/LQPHDJdF0Zc/s576/data_migration.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Apocalypse Now" by Francis Ford Coppola (1979)&lt;/span&gt;&lt;/div&gt;&lt;h2&gt;Diving into 'outsourcing applications with symfony': migrating data&lt;/h2&gt;&lt;p&gt;This post was inspired by &lt;a href="http://www.fizyk.net.pl"&gt;Fizyk&lt;/a&gt;'s &lt;a href="http://symfony-world.blogspot.com/2011/01/outsourcing-applications-with-symfony.html?showComment=1295252059895#c8357194602331033272"&gt;comment&lt;/a&gt; on the &lt;a href="http://symfony-world.blogspot.com/2011/01/outsourcing-applications-with-symfony.html"&gt;outsourcing applications with symfony&lt;/a&gt; article. Fizyk suggested that it would be a good idea to wrap all data migration functionalities into a symfony task(s). Basically, migrating data between different versions of the same project is the topic I want to focus on in this article.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;new version of a project, written from scratch&lt;/h2&gt;&lt;p&gt;In the previous article, we've been discussing developing a new version of an old project from scratch (e.g. because the old one was so inflexible that it was unable to be extended). &lt;u&gt;The first thing we should do is to design new database structure that will hold all data that the present project holds&lt;/u&gt; (I assume that the database structure will have to be different, because if it was good, no one would redevelop entire project from scratch). Depending on your luck, it can be an easy task or a nightmare [&lt;i&gt;I've already had redeveloped 2 projects with databases that were not even in the &lt;a href="http://en.wikipedia.org/wiki/First_normal_form"&gt;first normal form&lt;/a&gt;... yes, there are projects like this. Check this out: one of these projects were made by a really bad developer who never used any type of version control system. He used no development environment (only production) and no localhost machines to test new features before they are added. He made all modifications on the production server, even if it took 2 weeks until they were finished. And there was only FTP access on the server... Oh, yes, there ae projects like that... and you may be asked to improve such projects :)&lt;/i&gt;].&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;data migration&lt;/h2&gt;&lt;p&gt;Now when we have two parallel database structures, we need to copy all data from the old one to the new one. Depending on the data (its size, structure, relations, constraints, etc.), I use one of the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;pure Doctrine (Doctrine in - Doctrine out)&lt;/li&gt;&lt;li&gt;mixed (Doctrine in - SQL out)&lt;/li&gt;&lt;li&gt;pure SQL (SQL query)&lt;/li&gt;&lt;/ul&gt;For each data structure, I choose one of the above migration types very carefully (detailed descriptions below). If the project is big (and I assume this is the case), the development phase takes a lot of time. It's very important that you can run entire migration job:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;as fast as possible&lt;/b&gt;: this enables you to run the migration &lt;u&gt;very often&lt;/u&gt;, because it doesn't take too much time. And this gives you the possibility to &lt;u&gt;improve&lt;/u&gt; the scripts, &lt;u&gt;test them carefully&lt;/u&gt; (each mistake made during the migration will be painful when new project is started in production environment). And, finally, you can download the production (old project) database and migrate it to the new structure to compare the frontend of both projects - this helps to develop the business logic,&lt;/li&gt;&lt;li&gt;&lt;b&gt;with wrapped interface&lt;/b&gt;: click once - make yourself a cup of tea - come back in 10 minutes - click again - go out with your dog - come back in 15 minutes - the migration is done. Or otherwise: imagine you have a project with 50 tables and you have to run 50 actions (e.g. by a click), each one for each table - or call 50 symfony tasks, not to mention that you need to call them in appropriate order (because data is related in RDBMS) and you have to watch out not to break the order. Of course, there has to be 50 small jobs, deep inside the migration system, but your interface should do the work for you automatically (check an example below).&lt;/li&gt;&lt;li&gt;&lt;b&gt;avoid repeating the same manual modifications&lt;/b&gt;. This is difficult to discuss in general - I'll give an example. I've had an &lt;i&gt;action&lt;/i&gt; table which stored users activity. The old project database had a record which stated that &lt;i&gt;user X&lt;/i&gt; has replied to &lt;i&gt;topic Y&lt;/i&gt; with &lt;i&gt;post Z&lt;/i&gt;. And neither &lt;i&gt;topic Y&lt;/i&gt; nor &lt;i&gt;post Z&lt;/i&gt; existed in the database (again, if the project is so bad that it has to be redeveloped from scratch, such bad mistakes are very common). Of course, the migration system failed each time when symfony tried to insert a record that was related to a non-existent record. &lt;u&gt;What to do&lt;/u&gt;?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;bad solution&lt;/b&gt;: remove this &lt;i&gt;action&lt;/i&gt; record from you old database local copy (you download the old project database from the production server, load it to your SQL localhost machine and everythng is 100% safe)&lt;/li&gt;&lt;li&gt;&lt;b&gt;good solution&lt;/b&gt;: remove this record from production database, because it already points some stupid and non-existing stuff.&lt;/li&gt;&lt;/ul&gt;&lt;u&gt;Why to do so&lt;/u&gt;? Because if such mistakes were made in the old project (data inconsistency), there can be quite a lot of such paniful &lt;i&gt;action&lt;/i&gt; table, which will make a single migration job really long. And after you have done the whole migration 2 or 3 times, it'll be enough or dumb work and you won't want to do it any more. Again, this is only a simple example. Each situation will probably need a different solution&lt;/li&gt;&lt;/ul&gt;There is one more important thing: &lt;b&gt;no matter how complicated your migration job is, always create a detailed list of steps to make, describing what is being done at the moment, why such order and what is already migrated/what is still waiting to be migrated&lt;/b&gt;. With such list, performing data migration is really easy and unstressful :)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here you have an example of a migration job order from a project I did recently (all .sql files are '&lt;i&gt;pure SQL&lt;/i&gt;' migrations):&lt;br /&gt;&lt;a href="http://img863.imageshack.us/img863/3977/migrationjoborder.png"&gt;&lt;img src="http://img863.imageshack.us/img863/3977/migrationjoborder.th.png"&gt;&lt;/a&gt;&lt;br /&gt;where the action &lt;i&gt;http://polonia/backend_dev.php/migrator/migrateAll&lt;/i&gt; calls the following (these are the only '&lt;i&gt;pure Doctrine&lt;/i&gt;' migrations):&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateConfig&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateForbiddenPhrases&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateQuotes&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateArticles&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateReadingCategories&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateReadingTextbooks&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateCountries&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateRegions&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;MigrationManager&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;migrateSubpages&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;pure Doctrine migration&lt;/h2&gt;&lt;p&gt;This is the only code example in the &lt;a href="http://symfony-world.blogspot.com/2011/01/outsourcing-applications-with-symfony.html"&gt;outsourcing applications with symfony&lt;/a&gt; article. And this is probably the only migration type that would be wrapped in a symfony task, as &lt;a href="http://www.fizyk.net.pl"&gt;Fizyk&lt;/a&gt; suggested. This is really easy - just fetch data from the old system and save it in the new system.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;used for &lt;b&gt;small amounts of data&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;Below is another example of this data migration technique - private messages sent between users of a social website:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;static &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; migrateMessages&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$wiadomosci&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Wiadomosci w'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orderBy&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'w.wiad_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;fetchArray&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$wiadomosci&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; Message&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'wiad_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setTitle&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'temat'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setText&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'tresc'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setFromId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'wiad_od'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setToId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'wiad_do'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDisplayed&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'przeczytane'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setProvoke&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'zaczep'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;==&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'t'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setCreatedAt&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'kolumna_data'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setUpdatedAt&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'kolumna_data'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$message&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;save&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;pure SQL migration&lt;/h2&gt;&lt;p&gt;You may ask, why native SQL INSERT queries are constructed to be executed immediately, instead of using Doctrine? The answer is obvious: &lt;b&gt;time difference&lt;/b&gt;. Doctrine is nice, but in fact, it is really slow. The problem with &lt;i&gt;pure Doctrine migration&lt;/i&gt; is that it takes a lot of time to load all data with PHP/Doctrine and then to insert it into new structure. The table from the example above held over 50'000 records. At my local machine, it took several minutes to finish the job. It's too much (&lt;b&gt;data migration should be as fast as possible&lt;/b&gt;). The solution to this problem is simply to create a sql script that will do the job thousand times faster:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INSERT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INTO&lt;/span&gt; NEW_DB&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;message &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;  id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  title&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  text&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  from_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  to_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  displayed&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  provoke&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  created_at&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  updated_at&lt;br /&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;  wiad_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  temat&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  tresc&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  wiad_od&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  wiad_do&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  przeczytane&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IF&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;zaczep &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'t'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  kolumna_data&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  kolumna_data&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FROM&lt;/span&gt; OLD_DB&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;wiadomosci&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ORDER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;BY&lt;/span&gt; wiad_id&lt;/pre&gt;Sometimes the case may be even worse. The &lt;i&gt;action&lt;/i&gt; table, mentioned before, held over 400'000 records and the PHP/apache configuration would need really big limits (and the migration would take several hours to finish). The following is another sql script, migrating action data:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INSERT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INTO&lt;/span&gt; NEW_DB&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;action &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;  created_at&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  created_by&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  type_id_external&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  target_profile_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  forum_post_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  forum_topic_id&lt;br /&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SELECT&lt;/span&gt; kolumna_data&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; u_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;CASE akcja&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"profil"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"logowanie"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;2&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"wylogowanie"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;3&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"pm"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;4&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"zaczep"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;5&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"post"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;6&lt;/span&gt;&lt;br /&gt;  WHEN &lt;span style="color: rgb(255, 0, 0);"&gt;"watek"&lt;/span&gt; THEN &lt;span style="color: rgb(204, 102, 204);"&gt;7&lt;/span&gt;&lt;br /&gt;END&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IF&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;akcja &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'profil'&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;OR&lt;/span&gt; akcja &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'pm'&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;OR&lt;/span&gt; akcja &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'zaczep'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; akcja_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IF&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;akcja &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'post'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; post_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IF&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;akcja &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'watek'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; akcja_id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FROM&lt;/span&gt; OLD_DB&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;akcje &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ORDER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;BY&lt;/span&gt; kolumna_data &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ASC&lt;/span&gt;&lt;/pre&gt;Pure SQL migration may be a little bit more complicated (processing data in PHP is easier) - but you'll surely save a lot of time.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;used for &lt;b&gt;huge amounts of data&lt;/b&gt;, as this can be the only possibility to migrate it&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;mixed migration: Doctrine IN / SQL OUT&lt;/h2&gt;&lt;p&gt;Sometimes it can be impossible to create a magnificent "&lt;b&gt;INSERT INTO SELECT FROM&lt;/b&gt;" query. PHP, although being as slow as a dead snail (in comparison to SQL database management systems), still gives more possibilities just because being an imperative programming language. The idea of this migration type is to fetch the old system data using Doctrine, generate the SQL code and execute it. You may execute such generated script in any way you like - db console, tools like phpmyadmin or even forcing Doctrine to execute raw SQL. If someone prefers, this can be also done as a symfony task - but if the project is really big, you don't benefit from wrapping such mechanism into a symfony task.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;To fully understand the idea of this data migration type, take a look at the example below:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;static &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getInexistentProfileIds&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$u_ids&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Uzytkownicy u'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;select&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'u.u_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orderBy&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'u.u_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;fetchArray&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/range"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;range&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$u_ids&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;a href="http://www.php.net/count"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;count&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$u_ids&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'u_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$u_ids&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$u_id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;a href="http://www.php.net/unset"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;unset&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$u_id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'u_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;-&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;pre class="php" style="font-family: monospace;"&gt;static &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; generateSqlToRebuildUsers&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;self&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getInexistentProfileIds&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$sql&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'INSERT INTO profile (`id`) VALUES ('&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;a href="http://www.php.net/implode"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;implode&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'), ('&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;')'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sql&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'&amp;lt;hr /&amp;gt;'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$sql&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'INSERT INTO sf_guard_user (`id`, `email_address`, `username`,`is_active`) VALUES ('&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$ids&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$sql&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;.=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;',"NULL-'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'","NULL-'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'", 0), ('&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sql&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;The reason for doing mixed migration in this case is data inconsistency in the old project. Users were creating forum topics and posts. And when a user was deleted, posts and topics still referred to it. Migrating forum data returned dozens of errors, all of them was failing constraint - assigning topic/post to a non-existent user. The solution was to create &lt;i&gt;dead  user records&lt;/i&gt; (with deleted_at set), just for the SQL not to break the constraint. The first method fetches all IDs of the users that has been deleted, the second part generates the SQL code creating those dead records into the database. &lt;i&gt;This is only an example, of course, and the example above may be found controversial :), but, believe me, migrating an entire system (which was really, really badly developed) is a difficult task itself, the time you have is limited and sometimes you are forced to use somehow brutal solutions.&lt;/i&gt; Anyway, it's up to you how you want to grab the generated SQL code. For me it was the easiest way to display it in the browser, copy-paste to phpmyadmin and execute. But you can generate a sql file, wrap it into a symfony task or do whatever you think of. The main idea is just to make the data migration faster.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;and that's it&lt;/h2&gt;&lt;p&gt;I hope that some of my hints will be useful if you ever need to migrate data between different versions of the same project. Comments are welcome :)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-8797253678820255417?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/8797253678820255417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/05/data-migration-with-symfony-doctrine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8797253678820255417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8797253678820255417'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/05/data-migration-with-symfony-doctrine.html' title='data migration with symfony &amp; doctrine'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-3Nkk6wai95M/TzWHqNw2UaI/AAAAAAAAGuU/LQPHDJdF0Zc/s72-c/data_migration.png' height='72' width='72'/><thr:total>0</thr:total><georss:featurename>Central Europe</georss:featurename><georss:point>51.242897904529244 22.534503561767565</georss:point><georss:box>46.41290290452925 13.394686061767565 56.07289290452924 31.674321061767564</georss:box></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-29148809681805228</id><published>2011-04-18T01:11:00.000+02:00</published><updated>2011-12-15T22:49:01.986+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>faster queries: indexing tables</title><content type='html'>&lt;p&gt;When designing complex web applications, you have to pay attention to the project performance to make the framework handle your request as fast as possible. This involves optimising client side (clean CSS,  clean HTML, fast Javascript, etc.) and server side (caching templates and queries, usage of the database and many others). We will concentrate on the database here. In short, the database should have such structure that all information fetched to handle any request should be accessible very fast. This short article will show you few facts and tricks about symfony projects performance.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;built-in foreign key management&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;One of the brilliant features in symfony is creating indexes for foreign keys by default. This saves a lot of time for the developers and, surely, leverages the overall performance of all symfony applications. Below is an example schema:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;Book:&lt;br /&gt;  actAs:&lt;br /&gt;    Timestampable: ~&lt;br /&gt;    SoftDelete: ~&lt;br /&gt;  columns:&lt;br /&gt;    category_id:&lt;br /&gt;      type: integer&lt;br /&gt;      notnull: true&lt;br /&gt;      comment: "kategoria książek"&lt;br /&gt;    title:&lt;br /&gt;      type: string(255)&lt;br /&gt;      notnull: true&lt;br /&gt;      comment: "tytuł"&lt;br /&gt;    author:&lt;br /&gt;      type: string(255)&lt;br /&gt;      comment: "autor"&lt;br /&gt;    description:&lt;br /&gt;      type: string&lt;br /&gt;      comment: "opis"&lt;br /&gt;  relations:&lt;br /&gt;    Category:&lt;br /&gt;      class: BookCategory&lt;br /&gt;      local: category_id&lt;br /&gt;      foreign: id&lt;br /&gt;      foreignAlias: Books&lt;br /&gt;&lt;br /&gt;BookCategory:&lt;br /&gt;  actAs:&lt;br /&gt;    Timestampable: ~&lt;br /&gt;    SoftDelete: ~&lt;br /&gt;  columns:&lt;br /&gt;    name:&lt;br /&gt;      type: string(255)&lt;br /&gt;      notnull: true&lt;br /&gt;      comment: "nazwa"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Such schema will generate the following SQL code. Note that the &lt;strong&gt;book.category_id&lt;/strong&gt; column is indexed (faster queries) and constrainted (no data inconsistency) at the same time, &lt;strong&gt;automatically&lt;/strong&gt;:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;CREATE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; book_category &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id BIGINT &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;...&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;CREATE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; book &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id BIGINT &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INDEX&lt;/span&gt; category_id_idx &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;category_id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;...&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; book &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; CONSTRAINT book_category_id_book_category_id&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;category_id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; book_category&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Obviously, you may create your custom indexes (and this will be discussed later). This &lt;a href="http://www.symfony-project.org/doctrine/1_2/en/04-Schema-Files#chapter_04_indexes"&gt;section from &lt;i&gt;The symfony and Doctrine book&lt;/i&gt;&lt;/a&gt; covers the topic of custom indexes.&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;optimising MySQL queries&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;Before you do anything to speed up your queries execution, you need to know what queries you have in your system. The obvious thing is to look at the powerful &lt;strong&gt;web debug toolbar&lt;/strong&gt;. It's a great tool, but it won't tell you what to do when executing your queries takes too long. But it can point out which queries are definitely poorly written (they are highlighted with orange color then). Then it's time for you to solve the problem. Often, it may happen that you need to join tables (more about this is written in "&lt;a href="http://symfony-world.blogspot.com/2011/02/less-doctrine-queries-in-symfony-admin.html"&gt;less doctrine queries&lt;/a&gt;" article).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If the number of queries cannot be limited, probably you may need to add custom indexes on your tables. An index is an additional structure, bound to a table, that speeds up selecting the appropriate results (there are lots of good tutorials on this topic, such as &lt;a href="http://www.tizag.com/mysqlTutorial/mysql-index.php"&gt;the tizag tutorials&lt;/a&gt;). The database server, when executing any query, looks for the best structure that can be used to serve the results as fast as possible. We can ask our database server to analyse given any query to tell us how is it going to be executed. And the best tool to visualise this is the &lt;strong&gt;EXPLAIN&lt;/strong&gt; statement (&lt;a href="http://www.dbtuna.com/article.php?id=14"&gt;short reference here&lt;/a&gt;). We will optimise a heavy query executed on the homepage of a social website, using &lt;strong&gt;explain&lt;/strong&gt; and &lt;strong&gt;adding custom index&lt;/strong&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;example - social website homepage problem&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;The manager of the social website wants the developers to emphasise the users who are the most active ones. For example, he wants to display last logged users at the homepage. The developers figured out that they need to create an &lt;i&gt;action&lt;/i&gt; table that will store actions performed by users. &lt;i&gt;Action&lt;/i&gt; and &lt;i&gt;profile&lt;/i&gt; tables are related to each other - a simple &lt;strong&gt;JOIN&lt;/strong&gt; will be used each time when the homepage action is executed: last logged x profiles are fetched from the database and displayed then.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The website has been set off. Many users have registered and the action table is growing bigger and bigger every day. After few months, it has over 300'000 records. The manager is very happy that his project is becoming popular, but he noticed that the homepage is being served few seconds slower than it was in the beginning. The developers tell him that they didn't run high performance tests and they have to spend some time on optimisation. The manager is not pleased that it was not considered before.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;NOTE: always use test data when focusing on project performance&lt;/h1&gt;&lt;p&gt;Symfony has a built-in fixture mechanism which allows you to easily generate lots of different data (see the &lt;a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/03#chapter_03_the_initial_data"&gt;jobeet tutorial&lt;/a&gt;). This is essential when you want to make sure that your project will manage with big popularity. Anyway, if you decide to generate really big amount of data, do NOT use any ORM. It consumes too much memory and generating fixtures takes a lot of your precious time. I'd suggest to generate raw SQL INSERT queries instead - they'll be a lot faster.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Okay, let's move on. Once you have got lots of data (either real or test), execute each action - one after another - and check its performance. First thing you should look at is the mentioned &lt;strong&gt;web debug toolbar&lt;/strong&gt; in the top right corner of the screen when running &lt;strong&gt;dev application environment&lt;/strong&gt;. You should be worried, when you see something like the following:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://img251.imageshack.us/img251/2759/toolbart.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There is a big problem: at least one of the queries is unoptimal (orange color) and as a consequence, executing this action takes too much time (imagine, almost 5 secs per one execution is really long and it doesn't matter that I'm using my personal computer for testing). Left click on the query icon (the one to the right):&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://img163.imageshack.us/img163/4959/badquery.png"&gt;&lt;br /&gt;&lt;img src="http://img163.imageshack.us/img163/4959/badquery.th.png" /&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One query takes almost 4 seconds to be executed. This surely causes a serious performance problem! Don't panic, just let your database server analyse the query for you:&lt;/p&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;EXPLAIN&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SELECT&lt;/span&gt; a&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;id &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AS&lt;/span&gt; a__id&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; a&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;created_by &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AS&lt;/span&gt; a__created_by&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FROM&lt;/span&gt; action a&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;LEFT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;JOIN&lt;/span&gt; profile p &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;a&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;created_by &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;id &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AND&lt;/span&gt; p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;deleted_at &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IS&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;WHERE&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;    a&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;type_id_external &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'2'&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AND&lt;/span&gt; p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;avatar_id &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;IS&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AND&lt;/span&gt; p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;mode &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;4&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ORDER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;BY&lt;/span&gt; a&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;created_at &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DESC&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://img215.imageshack.us/img215/6981/explainbad.png"&gt;&lt;br /&gt;&lt;img src="http://img215.imageshack.us/img215/6981/explainbad.th.png" /&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here we can see, that the query has to check at least 1690 p (profile) table rows. And each profile record stores a lot of text data, describing each website user. All this makes the query take such long time to execute. If we want to speed it up, we just have to read carefully the query and concentrate on all columns used (and the order of their appearance). The solution is to find the best index (this topic may be quite complex and independent on the framework you use - ask google about indexing database tables/optimising databases - and read those articles carefully).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In this case, the developers executed the following line in MySQL:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; profile &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ADD&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INDEX&lt;/span&gt; deleted_at_idx &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;deleted_at&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;;&lt;/pre&gt;which created an index on the deleted_at datetime column. Thanks to this index, the &lt;i&gt;EXPLAIN&lt;/i&gt; command shows that only 10 different rows in the &lt;i&gt;profile&lt;/i&gt; table have to be analysed for the query to be executed. And this is a great success - the execution time went down to &lt;b&gt;0,01 second&lt;/b&gt;. Imagine the 4 seconds difference for each homepage display. This is the benefit from optimising project databases.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;By the way, I cannot understand why the &lt;i&gt;deleted_at&lt;/i&gt; column in the &lt;a href="http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors:core-behaviors:softdelete"&gt;SoftDelete&lt;/a&gt; behavior is not indexed by default, especially when you can turn on automatic not-null-check (sql callback):&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$manager&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setAttribute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;Doctrine_Core&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;ATTR_USE_DQL_CALLBACKS&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;Provided this line is present in the project configuration, each query that fetches a &lt;i&gt;SoftDelete&lt;/i&gt; model will automatically add the "WHERE deleted_at IS NOT NULL" part. It's obvious that such column has to be indexed - the index can be complex though - and the deleted_at can be the last column in this index - but, anyway, default index on deleted_at is a good idea! As you can see, &lt;b&gt;you have to pay attention to what queries are executed inside your projects&lt;/b&gt;!&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;h1&gt;Note: database server different versions use different indexes&lt;/h1&gt;&lt;p&gt;Different database server versions may use totally different indexes to execute the same queries on the same database structure! Make sure you run your performance test in the (future) production environment. Otherwise, you may find your application execute unoptimised queries on the production server even if you spent a lot of time optimising it in your local dev machine.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In the example above, it turned out that the production server has a different db server than the developer's local machine. The developer didn't check it - he was not aware of the differences and their negative impact on project's performance. The index that has been built is useless in the production environment (so it should be deleted, because inserting each row is slowed down by this index). Moreover, it happedened, that the new index the developers needed to speed up the query should be build on the &lt;i&gt;action&lt;/i&gt; table... &lt;b&gt;pay attention to database server versions you work on&lt;/b&gt;!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;how many indexes to create&lt;/h1&gt;&lt;p&gt;Table indexes are really helpful and they speed up database performance. The more complex your application is, the more queries may be executed. In other words, the bigger your application is, the more queries it may need to provide good performance. But look out - do not create too much indexes and &lt;strong&gt;never create any index when you are not sure that it is used somewhere&lt;/strong&gt;. Why? It's very simple - each index is an additional structure which uses some space and needs some time to be created and managed. When a record is inserted, updated or removed, each index has to be updated accordingly to the change made, which surely consumes time. If you create too many indexes, you may simply slow down your database. For example, each user login inserts new action record - then an action table with 10 indexes will be slower than an action table with only 3 indexes).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;further reading: &lt;a href="http://hackmysql.com/case4"&gt;this&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/3049283/mysql-indexes-what-are-the-best-practises"&gt;this&lt;/a&gt; and &lt;a href="http://www.mysqlfaqs.net/mysql-faqs/Indexes/What-are-best-practices-to-pick-columns-to-index"&gt;this&lt;/a&gt;&lt;/h1&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-29148809681805228?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/29148809681805228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/04/faster-queries-indexing-tables.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/29148809681805228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/29148809681805228'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/04/faster-queries-indexing-tables.html' title='faster queries: indexing tables'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-3112416815424617440</id><published>2011-03-29T20:34:00.000+02:00</published><updated>2012-02-10T22:52:35.590+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony validate database content with sfValidatorCallback</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-IqWwl_H2VKw/TzWRj40I76I/AAAAAAAAGus/RWFcs0k-05o/s1600/validator_callback.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-IqWwl_H2VKw/TzWRj40I76I/AAAAAAAAGus/RWFcs0k-05o/s576/validator_callback.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "The three Musketeers" by Stephen Herek (1993)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;In my last project, I needed to create a custom validation feature that would check if there are some specific records in database tables. You can read a lot about symfony validators &lt;a href="http://www.symfony-project.org/forms/1_4/en/B-Validators"&gt;at the official documentation&lt;/a&gt;, but I didn't found an exact solution to my problem there.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There are some &lt;b&gt;customers&lt;/b&gt; with their &lt;i&gt;names&lt;/i&gt; and their &lt;i&gt;security codes&lt;/i&gt; and there are some &lt;b&gt;offers&lt;/b&gt; that are bound to customers. There is a offer submission form in the frontend application, where the customer's name and security code have to be given. I found none of the simple validators useful. In the &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin"&gt;sfDoctrineGuardPlugin&lt;/a&gt; there is a sfGuardValidatorUser which is used to validate passwords in the signin form:&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setWidgets&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'username'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputText&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'password'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputPassword&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'type'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'password'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'remember'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputCheckbox&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setValidators&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'username'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorString&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'password'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorString&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'remember'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorBoolean&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;validatorSchema&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setPostValidator&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfGuardValidatorUser&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Take a look at the validator's class &lt;a href="http://trac.symfony-project.org/browser/plugins/sfDoctrineGuardPlugin/trunk/lib/validator/sfGuardValidatorUser.class.php"&gt;here&lt;/a&gt;. In short, the validator retrieves the user object and compares its password stored in the database with the one accessible from the request. As I mentioned, no simple validator can help, so a post validator has to be used on the entire validator schema:&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;validatorSchema&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setPostValidator&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfGuardValidatorUser&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;However, you can have the same effect without creating a custom validator. Symfony framework provides a &lt;a href="http://www.symfony-project.org/forms/1_4/en/B-Validators#chapter_b_sub_sfvalidatorcallback"&gt; callback validator&lt;/a&gt;:&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;validatorSchema&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setPostValidator&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorCallback&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'callback'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'customer_code_callback'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The &lt;i&gt;customer_code_callback&lt;/i&gt; has to be created now:&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; customer_code_callback&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$validator&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$customer_count&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Customer c'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'c.name = ?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'customer'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'c.code = ?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'code'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;count&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;!&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$customer_count&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    throw &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorError&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$validator&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Niepoprawny kod lub firma'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$values&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Following the principle &lt;i&gt;the simplest is the best&lt;/i&gt;, I'm doing almost the same stuff as the sfGuardValidatorUser, but with less work. Of course, it is up to you to decide whether you prefer to create a simple callback function or a reusable, entire validator class (which is more complicated, more elegant but provides the same functionality). So this is enough for the form to validate the customer's security code, before the offer file can be uploaded.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Of course, apart from the post validator, all form widgets can be validated with simple validators:&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setWidgets&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'customer'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputText&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'code'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputText&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfWidgetFormInputFile&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setValidators&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'customer'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorString&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'trim'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Podaj nazwę firmy'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'code'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorString&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'trim'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Podaj kod weryfikacyjny'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; sfValidatorFile&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'path'&lt;/span&gt;     &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;get&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_upload_dir'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'/offer/'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'required'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Wybierz załącznik'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;further usage&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The example I  gave seems quite similar to password check. But as you can see, you can just replace the example Doctrine query with any other queries, e.g.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;check number of offers submitted by a customer, which are still being processed (not finished), if their total count exceeds 10, the validation shall fail&lt;/li&gt;&lt;li&gt;check if there is any free machine/employee that can handle a service, requested by the user; for example, all machines are busy, the validation shows an error &lt;i&gt;you have to wait 36 minutes to wait for the first free machine&lt;/i&gt; and, optionally, store the IP to be handled as the first in the queue&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-3112416815424617440?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/3112416815424617440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/03/symfony-validate-database-content.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3112416815424617440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3112416815424617440'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/03/symfony-validate-database-content.html' title='symfony validate database content with sfValidatorCallback'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-IqWwl_H2VKw/TzWRj40I76I/AAAAAAAAGus/RWFcs0k-05o/s72-c/validator_callback.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4381688759341174258</id><published>2011-02-14T03:09:00.000+01:00</published><updated>2012-02-10T23:11:03.748+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>less doctrine queries in symfony admin modules</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-j6ugTakUviQ/TzWV4lWLOtI/AAAAAAAAGvE/BoFdPUxsjZA/s1600/less_doctrine_queries.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-j6ugTakUviQ/TzWV4lWLOtI/AAAAAAAAGvE/BoFdPUxsjZA/s576/less_doctrine_queries.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "The Damned" by Luchino Visconti (1969)&lt;/span&gt;&lt;/div&gt;&lt;h2&gt;basic stuff&lt;/h2&gt;&lt;p&gt;This short article is a hint for symfony newbies. I'll show how to configure admin modules to limit the number of SQL queries called to generate the list of result.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the problem&lt;/h2&gt;&lt;p&gt;The problem occurs when we create an admin module for a model that has some related records which we want to show. By default, Doctrine is not smart enough to guess that joining those related records will generate less SQL queries, so - depending on the database structure - generating a list of 20 objects can generate hundreds of queries (or even thousands, if the there are so many related records to be displayed). The example below is not so tragic, there are only 20 useless queries.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img20.imageshack.us/img20/6660/toolbarp.png" /&gt;&lt;br /&gt;&lt;br /&gt;By default, symfony calls a basic &lt;br /&gt;&lt;pre&gt;SELECT * FROM model;&lt;br /&gt;&lt;/pre&gt;query first. Then, while generating the row for each record, it calls for all related objects separately. As we can see below, these are the same queries run for different ids. A great waste of resources.&lt;br /&gt;&lt;br /&gt;&lt;a target='_blank' href='http://img143.imageshack.us/img143/4767/queries.png'&gt;&lt;img src='http://img143.imageshack.us/img143/4767/queries.th.png' border='0'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now, the thing is to make symfony call less SQL queries to do the same job.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the solution&lt;/h2&gt;&lt;p&gt;Let's say, we have a custom model called Proc, representing a procedure.&lt;br /&gt;&lt;br /&gt;&lt;img src='http://img84.imageshack.us/img84/5782/modulek.png' /&gt;&lt;br /&gt;&lt;br /&gt;Go to the &lt;i&gt;generator.yml&lt;/i&gt; file in the custom admin module config directory and add the &lt;strong&gt;table_method&lt;/strong&gt; option in the list section:&lt;br /&gt;&lt;pre&gt;generator:&lt;br /&gt;  class: sfDoctrineGenerator&lt;br /&gt;  param:&lt;br /&gt;    #...&lt;br /&gt;    config:&lt;br /&gt;      list:&lt;br /&gt;        table_method: &lt;b&gt;getListQuery&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;This means that the configuration tells the admin module controller that if it want to fetch objects to display in a list, it has to look for the &lt;strong&gt;getListQuery&lt;/strong&gt; in the &lt;i&gt;ProcTable&lt;/i&gt; class. So we shall define it:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; static &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getListQuery&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Proc p'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;leftJoin&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'p.Tags'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;And it's all. Fast, easy and clean.&lt;br /&gt;&lt;br /&gt;There's also a possibility to achieve the same goal by overriding the &lt;b&gt;buildQuery&lt;/b&gt; method in the actions class of the custom admin module (&lt;b&gt;apps/backend/modules/proc/actions.class.php&lt;/b&gt;), but it's &lt;u&gt;the dirty solution&lt;/u&gt; (thus it's not advisable):&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; buildQuery&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;buildQuery&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;leftJoin&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$query&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getRootAlias&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'.Tags'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;The result&lt;/h2&gt;&lt;p&gt;Now, each Proc object has all related Tag objects fetched already. In the previous situation, when symfony was generating a row for an object (in the admin module list) it called the object for its related objects. None were fetched, so SQL queries were called. Now, when the Proc object is called for its Tags, they're already there, so no additional SQL queries are called.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img43.imageshack.us/img43/2425/toolbarpost.png" /&gt;&lt;br /&gt;&lt;br /&gt;This limits number of queries and is very important (ignoring this may cause the server to go down frequently). Each action (not only admin module) should be optimised to make symfony call as little SQL queries as possible. Of course, you may join all related models, not only one (the Proc model could have more than only Tags relation, for example, Category, Author, Department and so on - each of them would generate useless queries as well).&lt;br /&gt;&lt;br /&gt;&lt;a target='_blank' href='http://img7.imageshack.us/img7/7610/queriespost.png'&gt;&lt;img src='http://img7.imageshack.us/img7/7610/queriespost.th.png' border='0'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Enjoy ;)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;i&gt;&lt;br /&gt;EDIT: This post was updated thanks to &lt;a href="http://www.fizyk.net.pl/"&gt;fizyk&lt;/a&gt;'s and &lt;a href="http://www.blogger.com/profile/14384060603804665440"&gt;sacri&lt;/a&gt;'s opinions. Thanks, guys ;).&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4381688759341174258?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4381688759341174258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/02/less-doctrine-queries-in-symfony-admin.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4381688759341174258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4381688759341174258'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/02/less-doctrine-queries-in-symfony-admin.html' title='less doctrine queries in symfony admin modules'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-j6ugTakUviQ/TzWV4lWLOtI/AAAAAAAAGvE/BoFdPUxsjZA/s72-c/less_doctrine_queries.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7050249884504685846</id><published>2011-02-06T20:01:00.000+01:00</published><updated>2012-02-10T13:42:45.390+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>documenting database with symfony doctrine</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-24mOPeITKEM/TzUOujRmeaI/AAAAAAAAGrc/WyTvyZXWXC8/s1600/database_documentation.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="226" width="336" src="http://4.bp.blogspot.com/-24mOPeITKEM/TzUOujRmeaI/AAAAAAAAGrc/WyTvyZXWXC8/s400/database_documentation.png" /&gt;&lt;span class="movie"&gt;Scene from "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb" by Stanley Kubrick (1964)&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;Symfony projects using Doctrine ORM have their schema defined in schema.yml files. There's a very nice &amp; useful feature, &lt;b&gt;setting comments to your table columns&lt;/b&gt; (which is probably not mentioned in the official docs).&lt;br /&gt;&lt;br /&gt;It's very easy - just set a &lt;i&gt;comment&lt;/i&gt; option to each of your columns, defining what this column holds, for example:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Customer&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Timestampable&lt;/span&gt;: ~&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;: ~&lt;br /&gt;  &lt;span style="color: blue;"&gt;columns&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;firstname&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;type&lt;/span&gt;: string(32)&lt;br /&gt;      &lt;span style="color: blue;"&gt;notnull&lt;/span&gt;: true&lt;br /&gt;      &lt;b&gt;&lt;span style="color: blue; font-weight:bold;"&gt;comment&lt;/span&gt;: "imię"&lt;/b&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;lastname&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;type&lt;/span&gt;: string(64)&lt;br /&gt;      &lt;span style="color: blue;"&gt;notnull&lt;/span&gt;: true&lt;br /&gt;      &lt;b&gt;&lt;span style="color: blue; font-weight:bold;"&gt;comment&lt;/span&gt;: "nazwisko"&lt;/b&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;email&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;type&lt;/span&gt;: string(64)&lt;br /&gt;      &lt;span style="color: blue;"&gt;notnull&lt;/span&gt;: true&lt;br /&gt;      &lt;b&gt;&lt;span style="color: blue; font-weight:bold;"&gt;comment&lt;/span&gt;: "adres E-mail"&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;The MySQL code generated for such schema is already with provided comments:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;CREATE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; customer &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;  id BIGINT &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  firstname VARCHAR&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;32&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt; COMMENT &lt;span style="color: rgb(255, 0, 0);"&gt;'imię'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  lastname VARCHAR&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;64&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt; COMMENT &lt;span style="color: rgb(255, 0, 0);"&gt;'nazwisko'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  email VARCHAR&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;64&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt; COMMENT &lt;span style="color: rgb(255, 0, 0);"&gt;'adres E-mail'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  created_at DATETIME &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; updated_at DATETIME &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  created_by BIGINT &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'1'&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  updated_by BIGINT &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'1'&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INDEX&lt;/span&gt; created_by_idx &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;created_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INDEX&lt;/span&gt; updated_by_idx &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;updated_by&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;id&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; CHARACTER &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SET&lt;/span&gt; utf8 COLLATE utf8_general_ci ENGINE &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; INNODB;&lt;/pre&gt;&lt;br /&gt;This is how phpmyadmin makes use of column comments:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img16.imageshack.us/img16/8164/customerj.png" /&gt;&lt;br /&gt;&lt;br /&gt;And below, you can see another example of comments usage - an important database table that many other tables rely on (click to enlarge):&lt;br /&gt;&lt;br /&gt;&lt;a href='http://img89.imageshack.us/img89/1636/sourcesm.png'&gt;&lt;img src='http://img89.imageshack.us/img89/1636/sourcesm.th.png' border='0'/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Short and precise description makes a table structure easier to be understood by a programmer.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It takes very little time to define those database comments. But it can save you a lot of time: either if you are working on a big project that has to be well-documented and need to review the structure or if the project is going to be extended by someone else who doesn't know what is where, or you may find it useful in many different situations.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7050249884504685846?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7050249884504685846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/02/documenting-database-with-symfony.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7050249884504685846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7050249884504685846'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/02/documenting-database-with-symfony.html' title='documenting database with symfony doctrine'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-24mOPeITKEM/TzUOujRmeaI/AAAAAAAAGrc/WyTvyZXWXC8/s72-c/database_documentation.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-8228546339108241901</id><published>2011-01-10T01:32:00.000+01:00</published><updated>2011-12-15T22:49:02.105+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>outsourcing applications with symfony</title><content type='html'>&lt;h2&gt;outsourcing applications&lt;/h2&gt;&lt;p&gt;When you need to write from scratch an application that already exists (it's too old to be maintained anymore or simply someone else has written hopelessly unmaintainable junk - and you're the big guy that got the job) - symfony is a good choice! In the following article, I'll concentrate mostly on model and data migration.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;overall&lt;/h2&gt;&lt;p&gt;The first task is to &lt;u&gt;prepare model for both (old &amp; new) systems&lt;/u&gt; (&lt;a href="http://www.symfony-project.org/doctrine/1_2/en/02-Connections#chapter_02_multiple_connections"&gt;multiple database connection&lt;/a&gt; used). Then, if the application already existed, the developer has to migrate all the date from the old structure to the new one, because it has to be available for the new system (e.g. already registered users). By &lt;i&gt;migration&lt;/i&gt; I mean simply copying data between two different structures. Data migration will be run many times during new system development and finally it will be run last time when the old system becomes history and the new one is switched on - data has to be up to date. So a &lt;u&gt;migration engine&lt;/u&gt; should be developed - this is the second task. And finally, the last one - a useful and handy tool to enable the developer to &lt;u&gt;easily modify models&lt;/u&gt;. Each of the three tasks will be described in details below.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;model for both systems&lt;/h2&gt;&lt;p&gt;Start with creating your local copy of the database that is used by the webpage you are about to refactor. Set up both connections in &lt;i&gt;config/databases.yml&lt;/i&gt; file. Now run&lt;br /&gt;&lt;pre&gt;./symfony doctrine:build-schema&lt;/pre&gt;to creates a schema from an existing database (for the old one). Define your new schema as well. I'd suggest to put them in separate files (e.g. new.yml and old.yml; for Doctrine you only need to put it in &lt;i&gt;config/doctrine&lt;/i&gt; directory, it doesn't have to be called exactly &lt;i&gt;schema.yml&lt;/i&gt;, can be &lt;i&gt;anything-else.yml&lt;/i&gt;).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;And the problem starts at this moment... For sure, you'll have to rebuild entire new system (database and all classes) - to modify originally designed database, because of some unpredicted stuff. But this will damage the old system database if you want to create SQL as well (and if the old one is really big, it'd be very annoying to load database dumps anytime you need to change schema). But the part is done - schemas for both systems are created (schema of the old system will never change - we don't care about it anymore).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;data migration&lt;/h2&gt;&lt;p&gt;For such task it's always better to create a separate class that will handle all data migration, we'll call it &lt;i&gt;MigrationManager&lt;/i&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Basically, one static method should perform data migration for one model (or more, if they're connected, like 1:n or m:n relations). If there'd be too many methods, you can always create more classes - it all depend on the project size. And if the old system data is really big, unfortunately, you won't be able to use Doctrine to insert new data. It consumes lots of memory to create Doctrine record objects. An example of what you can do to avoid the problem is to generate MySQL code (&lt;i&gt;INSERT INTO ...&lt;/i&gt;) - then the migration is performed in two steps - generate a database dump file and simply load it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If the amount of data doesn't force our local machine to use all it's memory (we can use Doctrine to insert data), it should be really easy:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;  /**&lt;br /&gt;   * Migrates data from old.aktualnosci to new.article.&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  static &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; migrateArticles&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$aktualnosci&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Aktualnosci a'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orderBy&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'a.news_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;fetchArray&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$aktualnosci&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; Article&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'news_id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setTitle&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'tytul'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setTextShort&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'skrot'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setTextFull&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'pelny'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setActive&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'aktywny'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setCreatedAt&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$row&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'kolumna_data'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;save&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;As you can see it's not difficult, even if you need to split or join the data or whatever. Then, enable using the &lt;i&gt;migrateArticles()&lt;/i&gt; method from the controller - e.g. create a &lt;i&gt;migrator&lt;/i&gt; module in the backend application, the module will have has distinct actions migrating different data. Calling any &lt;i&gt;MigrationManager&lt;/i&gt; method should result in inserting data to the new system which is equivalent to the old system data.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;easy schema/model modification tool&lt;/h2&gt;&lt;p&gt;Finally, the last and the most complicated task. As mentioned before, there'll be no need to modify the structure of the old system, as long as no one is working on it at the same time. But there has to be an easy way to modify new system structure.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Assuming we won't have to modify old system structure, I suggest to move all old system files into separate subdirectories of model, form and filter directories (you'll do it only once). For example, let's move them to &lt;i&gt;lib/doctrine/model/old&lt;/i&gt;, &lt;i&gt;lib/doctrine/form/old&lt;/i&gt; and &lt;i&gt;lib/doctrine/filter/old&lt;/i&gt; (and base Doctrine classes to &lt;i&gt;lib/doctrine/model/old/base&lt;/i&gt;, &lt;i&gt;lib/doctrine/form/old/base&lt;/i&gt; and &lt;i&gt;lib/doctrine/filter/old/base&lt;/i&gt; respectively). Moving those files to separate directories gives us two advantages: [1] we'll be able to temporarily get rid of all old connection model classes to make symfony leave old database alone (when running &lt;i&gt;doctrine:build --all&lt;/i&gt;) and [2] it simply separates two systems - it's more clear where to find which class.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We'll also need a versioning system like &lt;a href="subversion.tigris.org/"&gt;Subversion&lt;/a&gt;: after we temporarily delete class files, we'll retrieve them back.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;To make it all easier, I created two batch scripts that handle most of the job. Rebuilding new system structure requires doing 5 things:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;execute &lt;i&gt;remove_old&lt;/i&gt; script - delete everything that is connected with the old system (so that old system data won't be erased)&lt;/li&gt;&lt;li&gt;clearing cache - old connection classes shall be removed from cache also&lt;/li&gt;&lt;li&gt;doctrine:build --all - run the main task&lt;/li&gt;&lt;li&gt;committing all structure changes - using a versioning system, all changes will be saved, new system classes will replace their previous version so the versioning system will automatically note file differences&lt;/li&gt;&lt;li&gt;execute &lt;i&gt;model_reload&lt;/i&gt; script - get the original settings back&lt;/li&gt;&lt;/ul&gt;Examples of both scripts are provided below.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;remove old - script&lt;/h2&gt;&lt;p&gt;&lt;pre class="bash" style="font-family: monospace;"&gt;&lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'deleting old system files'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;old.yml&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;cp&lt;/span&gt; config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;databases.without-old.yml config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;databases.yml&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;model&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;old&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;form&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;old&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;filter&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;old&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'old system files deleted.'&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;old.yml&lt;/i&gt; file is the schema file holding old system structure. We delete it because we don't need those classes to be rebuild, especially that we moved them to a separate directory, so if they were rebuild, we would get two parallel set of classes (too bad...)&lt;/li&gt;&lt;li&gt;&lt;i&gt;databases.without-old.yml&lt;/i&gt; is the same as &lt;i&gt;databases.yml&lt;/i&gt; (two connections defined) with the only difference that the old connection is commented out (I prefer not to delete it just in case anything goes wrong with using versioning system).&lt;/li&gt;&lt;li&gt;removing class files - we don't have to list all classes separately (deleting entire directories is enough), because they've been separated from new system classes&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;model reload - script&lt;/h2&gt;&lt;p&gt;&lt;pre class="bash" style="font-family: monospace;"&gt;&lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'deleting new generated schema/model/form/filter'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;databases.yml&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;model&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;form&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;rm&lt;/span&gt; &lt;span style="color: rgb(102, 0, 51);"&gt;-fR&lt;/span&gt; lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;filter&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'model/form/filter deleted.'&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'restoring svn schema.'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;svn&lt;/span&gt; up config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;doctrine&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;svn&lt;/span&gt; up config&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;databases.yml&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'svn schema restored.'&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'restoring svn model.'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;svn&lt;/span&gt; up lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;model&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'svn model restored.'&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'restoring svn form.'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;svn&lt;/span&gt; up lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;form&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'svn form restored.'&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'restoring svn filter.'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;svn&lt;/span&gt; up lib&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;filter&lt;br /&gt;&lt;span style="color: rgb(122, 8, 116); font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'svn filter restored.'&lt;/span&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;removing everything&lt;/li&gt;&lt;li&gt;retrieving it from the versioning system; the project has now acces to both databases and is up to date with both schema files!&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Test it yourself. Any feedback is welcome!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;p&gt;Take a look at the &lt;a href="http://symfony-world.blogspot.com/2011/05/data-migration-with-symfony-doctrine.html"&gt;data migration with symfony &amp; doctrine &lt;/a&gt; article which is a continuation of this article, inspired by Fizyk's comment.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-8228546339108241901?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/8228546339108241901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2011/01/outsourcing-applications-with-symfony.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8228546339108241901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8228546339108241901'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2011/01/outsourcing-applications-with-symfony.html' title='outsourcing applications with symfony'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-3277374552680517844</id><published>2010-12-31T11:38:00.000+01:00</published><updated>2012-01-15T22:13:53.533+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><title type='text'>symfony sfAdminDashPlugin icons</title><content type='html'>&lt;p&gt;&lt;a href="http://www.symfony-project.org/plugins/sfAdminDashPlugin"&gt;sfAdminDashPlugin&lt;/a&gt; is one of the most useful symfony plugins (it's the &lt;a href="http://www.symfony-project.org/plugins/popular/"&gt;8th most popular plugin&lt;/a&gt; at the moment). I want to show few ways how to easily extend your backend application with custom icons: where to get them from and how to make your project use them. It seems not very complicated - and it's not :)! But the way your website looks like is still very important.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://img697.imageshack.us/img697/7734/logincb.png" /&gt;&lt;br /&gt;&lt;i&gt;sfAdminDashPlugin built-in login screen&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;sfAdminDashPlugin is provided with &lt;a href="http://svn.symfony-project.com/plugins/sfAdminDashPlugin/trunk/web/images/icons/"&gt;some standard icons&lt;/a&gt;, but probably you'll need more of them. Especially that it's really easy to add new ones - just follow these steps:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;find icon(s) that have the folowing sizes: &lt;b&gt;16x16&lt;/b&gt; and &lt;b&gt;48x48&lt;/b&gt;, should be in &lt;b&gt;.png&lt;/b&gt; format and be &lt;b&gt;transparent&lt;/b&gt; in the background&lt;/li&gt;&lt;li&gt;copy those files to the plugin directories: &lt;b&gt;PROJECT/plugins/sfAdminDashPlugin/web/images/icons&lt;/b&gt; - for the &lt;b&gt;48x48&lt;/b&gt; file and &lt;b&gt;PROJECT/plugins/sfAdminDashPlugin/web/images/icons/small&lt;/b&gt; for the &lt;b&gt;16x16&lt;/b&gt; file&lt;/li&gt;&lt;li&gt;use new icon(s) in your &lt;a href="http://www.symfony-project.org/plugins/sfAdminDashPlugin?tab=plugin_readme"&gt;config/app.yml configuration file&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;items:&lt;br /&gt;  Articles:&lt;br /&gt;    url:          article&lt;br /&gt;    image:        CustomIcon.png&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://img228.imageshack.us/img228/6388/defaultyk.png" /&gt;&lt;br /&gt;&lt;i&gt;set of icons provided with sfAdminDashPlugin&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;desktop environment&lt;/h2&gt;&lt;p&gt;The easiest place to look for your icons is your desktop environment resources directory. For example, I use KDE which stores its icons in&lt;br /&gt;&lt;pre&gt;/usr/share/icons/&lt;br /&gt;/usr/share/icons/default.kde4/16x16&lt;br /&gt;/usr/share/icons/default.kde4/48x48&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;external resources&lt;/h2&gt;&lt;p&gt;KDE has lots of icons added by users, which you can find &lt;a href="http://kde-look.org/index.php?xcontentmode=22x27"&gt;here&lt;/a&gt;. I have downloaded several packages and whenever I need a specific icon, I look through them. Good thing about icon themes is that large amount of icons are created in the same style, which would make your backend look even better!&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://img526.imageshack.us/img526/6055/nuvola.png" /&gt;&lt;br /&gt;&lt;i&gt;&lt;a href="http://kde-look.org/content/show.php?content=5358"&gt;nuvola&lt;/a&gt; KDE icon theme&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Of course, you may also find nice icons at special websites, such as&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.gettyicons.com"&gt;http://www.gettyicons.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.iconfinder.com"&gt;http://www.iconfinder.com&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;and many more (these two I use the most - to see the rest, ask google)...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://img211.imageshack.us/img211/6729/icons1.png" /&gt;&lt;br /&gt;&lt;i&gt;icon usage example&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img543.imageshack.us/img543/3431/menu2e.png" /&gt;&lt;br /&gt;&lt;i&gt;drop-down menu example&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img375.imageshack.us/img375/2958/icons2t.png" /&gt;&lt;br /&gt;&lt;i&gt;icon usage example&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img560.imageshack.us/img560/82/menub.png" /&gt;&lt;br /&gt;&lt;i&gt;drop-down menu example&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img153.imageshack.us/img153/3754/icons3v.png" /&gt;&lt;br /&gt;&lt;i&gt;icon usage example&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-3277374552680517844?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/3277374552680517844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/12/symfony-sfadmindashplugin-icons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3277374552680517844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/3277374552680517844'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/12/symfony-sfadmindashplugin-icons.html' title='symfony sfAdminDashPlugin icons'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-9077201119484213068</id><published>2010-11-29T01:05:00.000+01:00</published><updated>2012-01-15T22:17:14.599+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='mail'/><title type='text'>simple mailing system with symfony - part I</title><content type='html'>&lt;p&gt;This article is the beginning of a tutorial presenting an easy way to implement database-templated-mailing system for symfony projects.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the basics&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The basic version uses 2 tables: &lt;b&gt;mail_queue&lt;/b&gt; and &lt;b&gt;mail_template&lt;/b&gt;. For each type of mails, one template object is created.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;mail_template&lt;/h3&gt;&lt;p&gt;&lt;i&gt;name&lt;/i&gt;, &lt;i&gt;description&lt;/i&gt; - name &amp; description of the template&lt;br /&gt;&lt;i&gt;template_code&lt;/i&gt; - (HTML, including variables marked as {variable})&lt;br /&gt;&lt;i&gt;template_data&lt;/i&gt; - what variables are defined, just a description, no calculations performed&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For each single mail to be sent, one queue object is created.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;mail_queue&lt;/h3&gt;&lt;p&gt;&lt;i&gt;template_id&lt;/i&gt; - which template to use&lt;br /&gt;&lt;i&gt;mail_data&lt;/i&gt; - serialized array: variables=&gt;values&lt;br /&gt;&lt;i&gt;mail_recipent&lt;/i&gt; - formatted/serialized recipent information&lt;br /&gt;&lt;i&gt;mail_author&lt;/i&gt; - as above&lt;br /&gt;&lt;i&gt;mail_subject&lt;/i&gt; - string&lt;br /&gt;&lt;i&gt;send_at&lt;/i&gt; - time that this email should be sent&lt;br /&gt;&lt;i&gt;sent&lt;/i&gt; - boolean, already sent&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img31/3105/dbdw.png" alt="Table structure for mail_template and mail_queue tables" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;E-mail is sent when &lt;i&gt;sent&lt;/i&gt;=0 (and marked 1 afterwards, not to be sent again; in case of errors - mark as 2) and when actual time has gone beyond &lt;i&gt;send_at&lt;/i&gt;. &lt;i&gt;send_at&lt;/i&gt; column is especially useful, as you may create emails in a long time advance. For example, you want to send a reminder E-mail: create a new &lt;i&gt;MailQueue&lt;/i&gt; object with its datetime value equal to current timestamp + two weeks. This would make the E-mail to be sent in two weeks time from now.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;example usage&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;What kind of mails can we define? It depends on your project functionalities. For example, if your project is a stock managing software that stores information about products and their states, you can send important E-mails when one of the following situations take place:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;status of a product is changing - other employees shall be informed about that,&lt;/li&gt;&lt;li&gt;quantity of a product reached alarming level - supply needed immediately,&lt;/li&gt;&lt;li&gt;inform customers when product becomes available again,&lt;/li&gt;&lt;li&gt;and so on...&lt;/li&gt;&lt;/ul&gt;A template object is created for each of the situations defined above. There's a MailTools class with static methods processing mail sending. Just like notifyProductStatusHasChanged method, taking two parameters: Product and status change. This method creates a mail_queue instance, defining specific data for this type of E-mail, using Article object passed as the parameter.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;some details on implementation&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Symfony Swift Mailer integration is provided with a &lt;a href="http://www.symfony-project.org/more-with-symfony/1_4/en/04-Emails#chapter_04_the_delivery_strategy"&gt;ready to use mail queueing system&lt;/a&gt;. However, I decided to create a special task, defined to send E-mails that are marked with &lt;i&gt;sent&lt;/i&gt;=0. The code is pretty obvious:&lt;br /&gt;&lt;/p&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$mails&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getTable&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'MailQueue'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getMails2bSentQuery&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;execute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$mails&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$m&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$m&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;send&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Above task is run by a cron job (every few minutes). &lt;i&gt;getMails2bSentQuery&lt;/i&gt; method looks for &lt;i&gt;MailQueue&lt;/i&gt; objects that have &lt;i&gt;sent&lt;/i&gt;=0 and &lt;i&gt;send_at&lt;/i&gt; &lt;= now. For each of those objects, the template code (HTML) is filled with variable data and sent afterwards. The mail data is unserialized first and each variable is injected into the HTML code using str_replace function:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; generateContent&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$code&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getTemplate&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getTemplateCode&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$data&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/unserialize"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;unserialize&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getMailData&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$data&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$key&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$code&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/str_replace"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;str_replace&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'{'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$key&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'}'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$value&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$code&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$code&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Each mail template is defined using HTML/CSS code. It works similar to &lt;a href="http://www.smarty.net/"&gt;smarty template engine&lt;/a&gt;. Just define a list of variables of and all occurences of {VARIABLE} will be replaced with the parameter value you pass.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;to be continued&lt;/h2&gt;&lt;p&gt;This was just a brief overview. In the near future, precise code examples will be provided in tutorial's part 2.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-9077201119484213068?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/9077201119484213068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/11/simple-mailing-system-with-symfony-part.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/9077201119484213068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/9077201119484213068'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/11/simple-mailing-system-with-symfony-part.html' title='simple mailing system with symfony - part I'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-2234776952290889341</id><published>2010-11-01T02:28:00.000+01:00</published><updated>2012-02-10T18:19:23.815+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='behavior'/><title type='text'>Doctrine SoftDelete behavior usage</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-uSdMUe45WOM/TzUqepWTWSI/AAAAAAAAGsk/UROM41NTT4w/s1600/neverending_story.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-uSdMUe45WOM/TzUqepWTWSI/AAAAAAAAGsk/UROM41NTT4w/s576/neverending_story.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "The Neverending Story" by Wolfgang Petersen (1984)&lt;/span&gt;&lt;/div&gt;&lt;h2&gt;SoftDelete&lt;/h2&gt;&lt;p&gt;Recently, I created a &lt;a href="http://symfony-world.blogspot.com/2010/10/symfonydoctrine-behavior-review.html"&gt;detailed list of Doctrine behaviors&lt;/a&gt; ready to use in symfony projects. Among them, there is the &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors/zh#core-behaviors:softdelete"&gt;SoftDelete&lt;/a&gt; behavior I want to focus on this time. For a chosen model, it adds a &lt;i&gt;deleted_at&lt;/i&gt; column, which defines if a record has been marked as deleted (and if so, when).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;where to use it?&lt;/h2&gt;&lt;p&gt;Suppose your system needs to store all the detailed data history, every modification has to be marked and stay there forever. And even if the application allows users to delete objects, they are not really deleted - it is just an abstraction layer - in fact, objects are marked as deleted, but they stay in the database (and the application treats them as if they were deleted). This is where &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors/zh#core-behaviors:softdelete"&gt;SoftDelete&lt;/a&gt; comes handy.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;the code&lt;/h2&gt;&lt;p&gt;All you gotta do is just to state that a given model is SoftDelete:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;GivenModel&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;SoftDelete&lt;/span&gt;: ~&lt;br /&gt;&lt;/pre&gt;After this, the &lt;i&gt;deleted_at&lt;/i&gt; column is added (of course, both to SQL and PHP class). But that's not all the job. Unfortunately, you have to tell the application how to use this column manually. Fortunately, this is really easy. For example, if you have an admin generated module, soft-deleted objects shall never appear in the list. Add/modify the &lt;i&gt;buildQuery&lt;/i&gt; action of the admin module:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;protected &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; buildQuery&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; parent&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;buildQuery&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'deleted_at IS NULL'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;Additionally, if you want to have a full protection, you should update your admin module &lt;b&gt;edit&lt;/b&gt; action to disable executing it for a soft-deleted object. So this was for the backend. For frontend, you shall modify your eventual data retrieving table class methods, like the following:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; getObjectByIdQuery&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'GivenModel gm'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'gm.id = ?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'gm.deleted_at IS NULL'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;Of course, soft-deleted objects can &lt;b&gt;NEVER&lt;/b&gt; be accessible from any type of frontend applications. There is no way to give a detailed list of modifications you need to provide 100% data protection, because all applications have different structure - you have to go through your functionalities on your own. These code lines above are just examples you will probably use.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;enable DQL callbacks&lt;/h2&gt;&lt;p&gt;Alternatively, you may enable DQL callbacks for your models in each of your config/ProjectConfiguration.class.php files:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; configureDoctrine&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;Doctrine_Manager &lt;span style="color: rgb(0, 0, 136);"&gt;$manager&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// Enable callbacks so that softDelete behavior can be used&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$manager&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setAttribute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;Doctrine_Core&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;ATTR_USE_DQL_CALLBACKS&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;this will dynamically add an &lt;b&gt;andWhere DQL&lt;/b&gt; clause to all &lt;b&gt;SELECT&lt;/b&gt; queries for SoftDelete models (&lt;i&gt;Doctrine_Template_Listener_SoftDelete::preDqlDelete()&lt;/i&gt;). Thanks to it, you don't have to manually update all possible &lt;b&gt;SELECT&lt;/b&gt; queries in your project (such as &lt;b&gt;buildQuery&lt;/b&gt; mentioned above).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;be careful!&lt;/h2&gt;&lt;p&gt;As the official behavior docs say, &lt;i&gt;SoftDelete overrides the &lt;b&gt;delete()&lt;/b&gt; method. When &lt;b&gt;delete()&lt;/b&gt; is called, instead of deleting the record from the database, a &lt;b&gt;deleted_at&lt;/b&gt; date is set&lt;/i&gt;. This means, if you try to delete records &lt;u&gt;without&lt;/u&gt; using &lt;i&gt;Doctrine_Record::delete()&lt;/i&gt; method, &lt;b&gt;SoftDelete won't work&lt;/b&gt;! To provide 100% data protection covering SoftDelete you should replace all code like&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;delete&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'GivenModel gm'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'gm.id = ?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;execute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;with&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$objects&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Manufacturer m'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'m.id = ?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$id&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;execute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$objects&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$object&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$object&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;delete&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;to make the &lt;i&gt;Doctrine_Record::delete()&lt;/i&gt; be called whenever an object is supposed to be deleted, which finally means that the desired SoftDelete behavior is fired always when it should be.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;objects related to SoftDelete-able objects&lt;/h2&gt;&lt;p&gt;But there comes another question - what to do with related records of a soft-deleted object? For example, we have two model classes with the &lt;b&gt;SoftDelete&lt;/b&gt; behavior: &lt;b&gt;Manufacturer&lt;/b&gt; and &lt;b&gt;Supplier&lt;/b&gt; which have a m:n relation table, &lt;b&gt;ManufacturerSupplier&lt;/b&gt; which defines who supplies which manufacturers. If some specific manufacturer and supplier objects are marked as soft-deleted, their corresponding &lt;b&gt;ManufacturerSupplier&lt;/b&gt; object (if it exists, let's suppose it does) is left and no one knows how to treat it. It is not marked as soft-deleted, since it hasn't got &lt;b&gt;SoftDelete&lt;/b&gt; behavior. And it still exists in the database, like a full-fledged record. Probably, it does &lt;u&gt;not&lt;/u&gt; raise any application problems, but there is a data consistency question - &lt;i&gt;what does such m:n table record represent, when at least one of its related objects are soft-deleted&lt;/i&gt;? Shall it be soft-deleted after the related master object is soft-deleted? Or maybe hard-deleted?&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-2234776952290889341?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/2234776952290889341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/10/doctrine-softdelete-behavior-usage.html#comment-form' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2234776952290889341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2234776952290889341'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/10/doctrine-softdelete-behavior-usage.html' title='Doctrine SoftDelete behavior usage'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-uSdMUe45WOM/TzUqepWTWSI/AAAAAAAAGsk/UROM41NTT4w/s72-c/neverending_story.png' height='72' width='72'/><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7235698647588750691</id><published>2010-10-07T19:10:00.000+02:00</published><updated>2012-01-15T22:20:47.758+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>MySQL error on rename when dropping column with a constraint</title><content type='html'>&lt;h2&gt;a nasty MySQL bug&lt;/h2&gt;&lt;br /&gt;Recently I wanted to remove a column from phpmyadmin that is covered with a constraint. Impossible to do so, MySQL throws following error:&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;ERROR 1025 (HY000): Error on rename of './optiner_prestadmin/#sql-6bc_3e6' to './optiner_prestadmin/order_history' (errno: 150)&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;You may get above error when executing a query removing index, e.g.&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; order_history &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DROP&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;INDEX&lt;/span&gt; user_id;&lt;/pre&gt;Fortunately, there is a solution, not very easy to find in the internet (I used comments from &lt;a href="http://www.simplicidade.org/notes/archives/2008/03/mysql_errno_150.html"&gt;this article&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;execute the following in MySQL:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SHOW&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;CREATE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; order_history;&lt;/pre&gt;You shall get something like:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;order_history &lt;span style="color: rgb(102, 204, 102);"&gt;|&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;CREATE&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`order_id`&lt;/span&gt; bigint&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;20&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`user_id`&lt;/span&gt; bigint&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;20&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`status_id`&lt;/span&gt; bigint&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;20&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`informed`&lt;/span&gt; tinyint&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'0'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`comment`&lt;/span&gt; text&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`created_at`&lt;/span&gt; datetime &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(255, 0, 0);"&gt;`created_by`&lt;/span&gt; bigint&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;20&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NOT&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;NULL&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;'1'&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_id_idx`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`order_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`user_id_idx`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`user_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`status_id_idx`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`status_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`created_by_idx`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`created_by`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  CONSTRAINT &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history_created_by_sf_guard_user_id`&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`created_by`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`sf_guard_user`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ON&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DELETE&lt;/span&gt; CASCADE&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  CONSTRAINT &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history_order_id_order_info_id`&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`order_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_info`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  CONSTRAINT &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history_status_id_order_status_id`&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`status_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_status`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt;&lt;br /&gt;  CONSTRAINT &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history_user_id_sf_guard_user_id`&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`user_id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;REFERENCES&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`sf_guard_user`&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`id`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; ENGINE&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;InnoDB &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(204, 102, 204);"&gt;28305&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DEFAULT&lt;/span&gt; CHARSET&lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt;utf8&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;we want to delete the whole column &lt;b&gt;user_id&lt;/b&gt; (with all corresponding indices, constraints, etc.) - need to drop the &lt;b&gt;FOREIGN KEY&lt;/b&gt; first:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; order_history&lt;br /&gt;  &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DROP&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;KEY&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history_user_id_sf_guard_user_id`&lt;/span&gt;;&lt;/pre&gt;you'll find the name of the foreign key in the last constraint clause.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;finally, drop the column:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;ALTER&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;TABLE&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`order_history`&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;DROP&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;`user_id`&lt;/span&gt;;&lt;/pre&gt;and that's it!&lt;br /&gt;&lt;pre&gt;Query OK, 28065 rows affected (3,99 sec)&lt;br /&gt;Records: 28065  Duplicates: 0  Warnings: 0&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7235698647588750691?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7235698647588750691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/10/mysql-error-on-rename-when-dropping.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7235698647588750691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7235698647588750691'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/10/mysql-error-on-rename-when-dropping.html' title='MySQL error on rename when dropping column with a constraint'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-5968137390756313056</id><published>2010-10-05T22:56:00.000+02:00</published><updated>2012-02-10T13:16:27.262+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='behavior'/><title type='text'>symfony &amp; Doctrine behavior review</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://libreaction.files.wordpress.com/2011/07/lego_bricks.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="375" width="500" src="http://libreaction.files.wordpress.com/2011/07/lego_bricks.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h2&gt;Doctrine behaviors&lt;/h2&gt;&lt;p&gt;The main idea of this article is to create a short summary on Doctrine behaviors (really powerful and useful tools) which speed up development significantly. I tried to mention the most important behaviors, providing brief description and links. It's quite common to reinvent the wheel, being just unconscious that someone has already implemented a feature you are just in need of. Moreover, I hope that both beginners and advanced symfony developers will find this article a useful source of brief information about Doctrine behaviors &lt;u&gt;for everyday use&lt;/u&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Basically, a &lt;strong&gt;behavior&lt;/strong&gt; lets you share some relations, algorithms and other features among your project's model. They are (or at least should be) highly configurable: providing you a mechanism that can be easily customized to fit in different projects. Customization usually includes: enabling/disabling some of the behavior features (you may use only some of them), renaming additional schema columns, configuring them (like adding 'not null'), etc. You can use many Doctrine behaviors in your projects: core behaviors, Doctrine extensions, symfony plugins - or if you've got nothing better to do late at nights - you can create your own behaviors ;)&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Core behaviors&lt;/h2&gt;&lt;p&gt;The Doctrine ORM is bundled with several behaviors (calles &lt;i&gt;core behaviors&lt;/i&gt;), these are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Aversionable/en"&gt;Versionable&lt;/a&gt;&lt;/strong&gt; - add an entire &lt;i&gt;XxxVersion&lt;/i&gt; table to store your Xxx model object versions as either only version numbers or numbers versions along with ALL column data - to see object data changes through time,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Atimestampable/en"&gt;Timestampable&lt;/a&gt;&lt;/strong&gt; - probably the most popular of all behaviors, adds &lt;i&gt;created_at&lt;/i&gt; and &lt;i&gt;updated_at&lt;/i&gt; timestamp columns to your model, automatically saving datetime when a record is created or updated, respecticely,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Asluggable/en"&gt;Sluggable&lt;/a&gt;&lt;/strong&gt; - adds a &lt;i&gt;slug&lt;/i&gt; column that stores a &lt;a href="http://www.symfony-project.org/jobeet/1_4/Doctrine/en/05"&gt;slug&lt;/a&gt; which is a unique index automatically and can be used along with sfDoctrineRoute class to refer to an object without passing its ID as a parameter; by default the update is disabled, since this may harm your search engines rating,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Ai18n/en"&gt;I18n&lt;/a&gt;&lt;/strong&gt; - add an entire &lt;i&gt;XxxTranslation&lt;/i&gt; table to provide &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/13-I18n-and-L10n#chapter_13_text_information_in_the_database"&gt;Internationalization (I18n)&lt;/a&gt; for your Xxx model, essential when developing a multi-language project,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Anestedset/en"&gt;NestedSet&lt;/a&gt;&lt;/strong&gt; - adds &lt;i&gt;root_id&lt;/i&gt;, &lt;i&gt;lft&lt;/i&gt;, &lt;i&gt;rgt&lt;/i&gt; and &lt;i&gt;level&lt;/i&gt; columns to your model to develop an advanced hierarchical data structure (such as product categories), nested sets is an alternative to adjacency model, &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/hierarchical-data/en"&gt;more details on hierarchical data here&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Asearchable/en"&gt;Searchable&lt;/a&gt;&lt;/strong&gt; - choose model columns you want to index and add an entire database table, speeding up a basic search engine development, &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/searching/en"&gt;more info about searching here&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Ageographical/en"&gt;Geographical&lt;/a&gt;&lt;/strong&gt; - adds &lt;i&gt;longitude&lt;/i&gt; and &lt;i&gt;latitude&lt;/i&gt; columns storing geographical coordinates. Ever needed to use &lt;a href="http://maps.google.com"&gt;gmaps&lt;/a&gt; in your project, along with &lt;a href="http://www.symfony-project.org/plugins/sfEasyGMapPlugin"&gt;sfEasyGMapPlugin&lt;/a&gt;? Not only this behavior suits the data structure you need, but also provides you with &lt;i&gt;getDistance()&lt;/i&gt; method to calculate distance between two &lt;i&gt;Geographical&lt;/i&gt; objects,&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors%3Acore-behaviors%3Asoftdelete/en"&gt;SoftDelete&lt;/a&gt;&lt;/strong&gt; - adds a &lt;i&gt;deleted_at&lt;/i&gt; column which defines if a record has been marked as deleted (and if so, when). Useful when designing a highly complicated system where data consistency is important and even if some data should be invisible in the backend, it should still remain in the database.&lt;/li&gt;&lt;/ul&gt;&lt;p/&gt;&lt;h2&gt;extension behaviors&lt;/h2&gt;&lt;p&gt;You may also use &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/extensions/en"&gt;Doctrine extensions&lt;/a&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/Blameable/"&gt;Blameable&lt;/a&gt; - adds an additional level of auditing capabilities to models, &lt;i&gt;blameable&lt;/i&gt; allows you to track who created or last updated any model in an environment with many users, &lt;i&gt;blameable&lt;/i&gt; is a great companion to &lt;i&gt;Timestampable&lt;/i&gt; behavior,&lt;/li&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/EventLoggable/"&gt;EventLoggable&lt;/a&gt;, &lt;a href="http://trac.doctrine-project.org/browser/extensions/EventLoggable/branches/1.2-1.0/docs/en/configuring.txt"&gt;readme&lt;/a&gt; - logs any Doctrine Events (pre/post Delete/Insert/...) fired upon a record, log type may be chosen (e.g. file) and events may be limited to the chosen ones only,&lt;/li&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/Localizable/"&gt;Localizable&lt;/a&gt; - gives you functionality to convert units of measurement (e.g. kilometers to miles, etc.) or any other conversions desirable,&lt;/li&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/Locatable/"&gt;Locatable&lt;/a&gt; - gives you functionality using the Google Maps API to automatically populate your model with latitude and longitide information using Google, a fantastic tool to use along with &lt;a href="http://www.symfony-project.org/plugins/sfEasyGMapPlugin"&gt;sfEasyGMapPlugin&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/Sortable/"&gt;Sortable&lt;/a&gt; - gives you sortable functionality to your models, enabling you to easily fetch next/previous objects, moving them up/down in a sorted list or swapping with another object,&lt;/li&gt;&lt;li&gt;&lt;a href="http://svn.doctrine-project.org/extensions/Taggable/"&gt;Taggable&lt;/a&gt; - adds Tagging capabilities, creates a &lt;i&gt;TaggableTag&lt;/i&gt; table and a &lt;i&gt;XxxTaggableTag&lt;/i&gt; table for each &lt;i&gt;taggable&lt;/i&gt; model, using refClass m:n db table relation, provides easy tag management: add, remove, remove all, set, etc, finally, gives you the possibility to get the most popular tags (for a tag cloud, for example) fetched either from chosen models or from all of them,&lt;/li&gt;&lt;/ul&gt;&lt;p/&gt;&lt;h2&gt;plugin behaviors&lt;/h2&gt;&lt;p&gt;Finally, there are also symfony plugins providing custom behaviors:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin"&gt;sfDoctrineActAsSignablePlugin&lt;/a&gt; - a well developed alternative to &lt;i&gt;blameable&lt;/i&gt; Doctrine extension,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsTaggablePlugin"&gt;sfDoctrineActAsTaggablePlugin&lt;/a&gt; - provides tag management (alternative to &lt;i&gt;taggable&lt;/i&gt; Doctrine extension), provides a tag cloud generation,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/csDoctrineActAsAttachablePlugin"&gt;csDoctrineActAsAttachablePlugin&lt;/a&gt; - associate various uploads with multiple models,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineJCroppablePlugin"&gt;sfDoctrineJCroppablePlugin&lt;/a&gt; - add user-croppable images to your models with a javascript image cropper,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineNestedSetPlugin"&gt;sfDoctrineNestedSetPlugin&lt;/a&gt; - a form and a validator providing easy &lt;i&gt;NestedSet&lt;/i&gt; behavior management,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/csDoctrineActAsCategorizablePlugin"&gt;csDoctrineActAsCategorizablePlugin&lt;/a&gt; - categorize your models, mix, match or separate multiple models into multiple nested/flat categories,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsRattablePlugin"&gt;sfDoctrineActAsRattablePlugin&lt;/a&gt; - rate Doctrine objects,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/vjCommentPlugin"&gt;vjCommentPlugin&lt;/a&gt; - provides &lt;i&gt;commentable&lt;/i&gt; behavior to comment news page, articles, etc,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/ajDoctrineLuceneablePlugin"&gt;ajDoctrineLuceneablePlugin&lt;/a&gt; - provides &lt;i&gt;luceneable&lt;/i&gt; behavior with &lt;a href="http://en.wikipedia.org/wiki/Lucene"&gt;Lucene&lt;/a&gt; full text integration,&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p/&gt;&lt;h2&gt;useful links about Doctrine behaviors:&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/plugins/filter"&gt;list of symfony behavior plugins&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.doctrine-project.org/blog/using-behaviors-to-share-relationship-properties"&gt;share properties between your models and one-to-one relationships&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.doctrine-project.org/blog/cookbook-recipe-relation-dql-behavior"&gt;add default query parts that are automatically added to your queries when you reference the specified relationships&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/more-with-symfony/1_4/en/08-Advanced-Doctrine-Usage"&gt;writing doctrine behavior&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://diem-project.org/diem-5-0/doc/en/reference-book/doctrine-behaviors"&gt;Diem behavior extensions&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/doctrine/1_2/en/04-Schema-Files#chapter_04_nesting_behaviors"&gt;nesting behaviors&lt;/a&gt;,&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;notes&lt;/h2&gt;&lt;p&gt;If you find any information missing, please, let me know. Hopefully, you'll find it useful, otherwise I'll lose the motivation to do such thing next time ;)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-5968137390756313056?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/5968137390756313056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/10/symfonydoctrine-behavior-review.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5968137390756313056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5968137390756313056'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/10/symfonydoctrine-behavior-review.html' title='symfony &amp; Doctrine behavior review'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4417937337325484368</id><published>2010-10-03T18:18:00.000+02:00</published><updated>2012-01-15T22:16:56.521+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><title type='text'>update record changes with sfDoctrineActAsSignablePlugin: Signable behavior</title><content type='html'>&lt;h1&gt;&lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin?tab=plugin_readme"&gt;sfDoctrineActAsSignablePlugin&lt;/a&gt;&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;The plugin is fairly simple, it contains only a Doctrine temlate and a template event listener (basic stuff to implement a new Doctrine Behavior). It was initially released by &lt;a href="http://www.nitralabs.com"&gt;Vitaliy Tverdokhlib&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;Signable Doctrine Behavior&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;The plugin provides a &lt;b&gt;Signable&lt;/b&gt; behavior ready to be used in your models:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Model&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;: ~&lt;br /&gt;&lt;/pre&gt;It works very similarly to &lt;a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/behaviors/zh#core-behaviors:timestampable"&gt;Timestampable&lt;/a&gt; behavior: &lt;b&gt;created_at&lt;/b&gt; and &lt;b&gt;updated_at&lt;/b&gt; timestamp columns are added, storing information about the datetime that a record was created and last updated. &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin?tab=plugin_readme"&gt;Signable&lt;/a&gt; adds &lt;b&gt;created_by&lt;/b&gt; and &lt;b&gt;updated_by&lt;/b&gt; columns storing information about the user that created or last updated a record.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The plugin may be used along with &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin"&gt;sfDoctrineGuardPlugin&lt;/a&gt;. This gives you a possibility to refer to the &lt;b&gt;sf_guard_user&lt;/b&gt; table. No additional configuration is needed, the plugin automatically checks if sfDoctrineGuardPlugin is installed.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;configuration&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;The most important thing you can configure is to choose the type of the user field: it can be either &lt;i&gt;string&lt;/i&gt; or &lt;i&gt;integer&lt;/i&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Model&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;created&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;type&lt;/span&gt;: string&lt;br /&gt;      &lt;span style="color: blue;"&gt;updated&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;type&lt;/span&gt;: integer&lt;br /&gt;&lt;/pre&gt;If &lt;i&gt;string&lt;/i&gt; type is chosen, you can simply display the name of the user (e.g. in frontend blog article display page), but can do nothing further. If you choose &lt;i&gt;integer&lt;/i&gt;, you store ID of the user, which gives you a possibility to refer to the user in the user database table (which gives you all possibilities of using user Doctrine model).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;You can configure the behavior to meet your needs. Let's take a look at some examples:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;br /&gt;The &lt;b&gt;created_by&lt;/b&gt; and &lt;b&gt;updated_by&lt;/b&gt; column names are the default ones. You may change them:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Model&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;created&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;name&lt;/span&gt;: creator_id&lt;br /&gt;        &lt;span style="color: blue;"&gt;type&lt;/span&gt;: integer&lt;br /&gt;      &lt;span style="color: blue;"&gt;updated&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;name&lt;/span&gt;: update_username&lt;br /&gt;        &lt;span style="color: blue;"&gt;type&lt;/span&gt;: string&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;You want to know which user has created a record only (meaning that the user who updated the record is not important). In this case, disable &lt;i&gt;udpated&lt;/i&gt; option:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Model&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;updated&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;disabled&lt;/span&gt;: true&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;You want to add the &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin?tab=plugin_readme"&gt;Signable&lt;/a&gt; behavior to models of an existing project that already maintaines lots of data. And you want the &lt;b&gt;created_by&lt;/b&gt;/&lt;b&gt;updated_by&lt;/b&gt; user to be not null, because there's always someone who creates or updates a record. In a big project (a CRM, ERP, etc.) it's a good solution to create a system user (with id=1 for example) who represents all system actions (a daemon creating/updating objects from cron tasks):&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;Model&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;actAs&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;Signable&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;created&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;options&lt;/span&gt;:&lt;br /&gt;          &lt;span style="color: blue;"&gt;notnull&lt;/span&gt;: true&lt;br /&gt;          &lt;span style="color: blue;"&gt;default&lt;/span&gt;: 1&lt;br /&gt;      &lt;span style="color: blue;"&gt;updated&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: blue;"&gt;options&lt;/span&gt;:&lt;br /&gt;          &lt;span style="color: blue;"&gt;notnull&lt;/span&gt;: true&lt;br /&gt;          &lt;span style="color: blue;"&gt;default&lt;/span&gt;: 1&lt;br /&gt;&lt;/pre&gt;In this case, adding &lt;b&gt;created_by&lt;/b&gt;/&lt;b&gt;updated_by&lt;/b&gt; database columns will fill them initially with 1 (system user) and you can refer to the user (e.g. using &lt;i&gt;getUser()&lt;/i&gt; method), being sure that there's always a user referenced. And all further modifications will store real user ids.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;real world examples&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;&lt;br /&gt;Blog articles are being added by application users. You add &lt;strong&gt;Signable&lt;/strong&gt; behavior (with type: string) and you may use:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$article&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getCreatedBy&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;u&gt;in the app frontend to display who submitted the article&lt;/u&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;br /&gt;An E-commerce applications management system: users (employees) log in to the system and create orders that customers submit. You add &lt;strong&gt;Signable&lt;/strong&gt; behavior (with type: integer). Whenever an order is created, the &lt;strong&gt;created_by&lt;/strong&gt; is filled with the user ID. &lt;u&gt;The application can generate statistics on which users added the most orders&lt;/u&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;No matter if your project is a complex management system with extended backend - or a small company website with mainly frontend developed - &lt;b&gt;you'll find this &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineActAsSignablePlugin?tab=plugin_readme"&gt;plugin&lt;/a&gt; useful&lt;/b&gt;!&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4417937337325484368?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4417937337325484368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/10/update-record-changes-with.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4417937337325484368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4417937337325484368'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/10/update-record-changes-with.html' title='update record changes with sfDoctrineActAsSignablePlugin: Signable behavior'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-6618135219472606486</id><published>2010-09-13T21:52:00.000+02:00</published><updated>2012-01-15T22:16:45.980+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><title type='text'>new releases of sfApplicationMapPlugin</title><content type='html'>&lt;h1&gt;application map&lt;/h1&gt;&lt;p&gt;&lt;a href="http://www.symfony-project.org/plugins/sfApplicationMapPlugin"&gt;sfApplicationMapPlugin&lt;/a&gt; is an easily configurable documentation-generator tool. It generates a graphical map of your applications using &lt;a href="http://www.graphviz.org/"&gt;GraphViz&lt;/a&gt; software. It is useful when you want to have an overwiev of a specific application or of a whole project - each module/admin-module is marked with all actions and their comments. Take a look at the &lt;a href="http://www.symfony-project.org/plugins/sfApplicationMapPlugin?tab=plugin_readme"&gt;plugin readme tab&lt;/a&gt; to see some examples. You need to have &lt;a href="http://www.graphviz.org/"&gt;GraphViz&lt;/a&gt; installed on your system to use the plugin.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://img841.imageshack.us/img841/8924/frontendcirco.png"&gt;&lt;img src="http://imgcash4.imageshack.us/img841/8924/frontendcirco.th.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;new release&lt;/h1&gt;&lt;p&gt;New plugin versions supporting symfony 1.2-1.4 has been released. Thanks to bugs reported by Gordon Bazeley, the plugin should work correctly with no dependency on operating system.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://a.imageshack.us/img840/9180/backendfdp.png"&gt;&lt;img src="http://a.imageshack.us/img840/9180/backendfdp.th.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;an official GraphViz-based software&lt;/h1&gt;&lt;p&gt;&lt;a href="http://www.symfony-project.org/plugins/sfApplicationMapPlugin"&gt;sfApplicationMapPlugin&lt;/a&gt; is listed as a Software Engineering Tool on the &lt;a href="http://www.graphviz.org/Resources.php#software-engineering"&gt;official Graphviz website&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;todo and contribution&lt;/h1&gt;&lt;p&gt;The main thing to be done is supporting plugins used in projects. Any contribution is welcome, as well as bug reports and questions.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-6618135219472606486?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/6618135219472606486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/09/new-releases-of-sfapplicationmapplugin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6618135219472606486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/6618135219472606486'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/09/new-releases-of-sfapplicationmapplugin.html' title='new releases of sfApplicationMapPlugin'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-2559958825498137922</id><published>2010-09-13T00:15:00.000+02:00</published><updated>2012-02-11T00:13:38.109+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>Symfony framework instead of a well-known CMS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-8Du3-Geve8s/TzWkdFztZZI/AAAAAAAAGv0/qS1SkYkMRZA/s1600/well_kown_cms.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-8Du3-Geve8s/TzWkdFztZZI/AAAAAAAAGv0/qS1SkYkMRZA/s576/well_kown_cms.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "All Friends Here" aka "Our Folks" aka "Sami Swoi" by Sylwester Chęciński (1967)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Recently I got involved in developing and deploying a small website promoting a book that has just been released. My coordinator asked me to choose one of the most popular Content Management Systems (&lt;a href="http://wordpress.org/"&gt;Wordpress&lt;/a&gt;, &lt;a href="http://www.joomla.org/"&gt;Joomla&lt;/a&gt;, &lt;a href="http://drupal.org/"&gt;Drupal&lt;/a&gt;) to deploy the site on. Since I have a very little experience with developing apps based on a full-featured CMS, I was not so happy to be forced to learn a CMS just for a single small project.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I was given a full, well-prepared layout. The first step was to replace the default layout with the one I have just received. I took a look at Wordpress (because it seems to be the easiest and the smallest CMS). A glance at the template files has given me an overview stating that I will really need to spend some time to fully understand the wordpress templating system. Of course, it doesn't mean that it's difficult or out of my reach - I'm just lazy, as most of us :) - and I prefer designing complex and complicated systems rather than studying boring wordpress engine...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I got an idea of giving up wordpress (after 20 minutes of reading documentation)... At first, it sounded quite crazy - to develop a small site with such a powerful tool like symfony. I asked myself questions like '&lt;i&gt;do I really need such an advanced tool to develop such a trivial project?&lt;/i&gt;' or '&lt;i&gt;how long is it going to take me to implement all mechanisms that are already implemented in wordpress (such as nice looking menu, panels, intuitive interface and so on)&lt;/i&gt;?' Maybe long... but the more I was analysing the time difference between designing the app in an unknown CMS and very well-known symfony framework, the more the symfony option was attractive.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Developing the frontend is only putting the new layout on. Backend is more complex. But still it's all very easy and extremely fast to use. Using &lt;a href="http://www.symfony-project.org/plugins/sfAdminDashPlugin"&gt;sfAdminDashPlugin&lt;/a&gt;, &lt;a href="http://www.symfony-project.org/plugins/sfJqueryReloadedPlugin"&gt;sfJqueryReloadedPlugin&lt;/a&gt; and &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin"&gt;sfDoctrineGuardPlugin&lt;/a&gt;, the greatest 3 symfony plugins, gave me the basis of a backend engine with many features ready to be improved (e.g. I could define user credentials, I could organise the backend menu, etc). I use these 3 plugins in 99% of my projects (and suppose more people do so) and it takes me very little time to configure those plugins.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Developing backend is mainly working with generator.yml/module interface configuration, because this part is usually different in all web apps (meaning that you can copy lots of model/form/filter methods from your previous projects, to save time). If you implement any feature and use it in any project, you can always copy it later to another project (or make yourself a plugin, which is usually a better choice, because the whole community may reuse your work). Just like my AJAX backend activate/deactivate feature (see &lt;a href="http://symfony-world.blogspot.com/2010/05/ajaxsymfony-easy-user-friendly-example.html"&gt;easy symfony ajax user friendly example&lt;/a&gt;) - after I managed to implement the feature (which originally could have taken me up to 3 hours, including studying entire symfony AJAX, ajax routing, sfJqueryReloaded and so on), now it takes me less than 5 minutes to copy it to a new place. Or to make a similar feature somewhere else. And imagine that some mechanisms, like taggable or commentable behavior can be put into plugins, which makes it even faster to use! This is one of the biggest symfony advantages - the speed on development. All of us shall use it as much as we can.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Choosing symfony for this project was a great decision. It saved me a lot of time, made me proud of how fast a small symfony project can be developed. Still, the code is comprehensible, it's kept well-documented (so the entire project is opened for any modifications). My experience I want to share with you is that &lt;b&gt;symfony is a good choice also for small projects&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-2559958825498137922?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/2559958825498137922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-framework-instead-of-well-known.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2559958825498137922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2559958825498137922'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-framework-instead-of-well-known.html' title='Symfony framework instead of a well-known CMS'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-8Du3-Geve8s/TzWkdFztZZI/AAAAAAAAGv0/qS1SkYkMRZA/s72-c/well_kown_cms.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-442322027501780271</id><published>2010-09-07T01:53:00.000+02:00</published><updated>2011-12-15T22:49:02.029+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony file upload - leave original file name</title><content type='html'>&lt;p&gt;If you want your uploaded files to stay with the original file name (which is not randomly generated by symfony), just add following lines to the model class you want to upload files:&lt;/p&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; generateXxxFileName&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$file&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$file&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getOriginalName&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;where &lt;i&gt;Xxx&lt;/i&gt; is the name of the column that stores the filename in the database model related table.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-442322027501780271?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/442322027501780271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-file-upload-leave-original-file.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/442322027501780271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/442322027501780271'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-file-upload-leave-original-file.html' title='symfony file upload - leave original file name'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-7065655020762025069</id><published>2010-09-06T00:51:00.000+02:00</published><updated>2012-02-10T23:56:48.155+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='task'/><title type='text'>symfony crons and cron task logging</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-oDS5xpKbno0/TzWeV2dzzDI/AAAAAAAAGvo/E4gJzzB97q8/s1600/task.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-oDS5xpKbno0/TzWeV2dzzDI/AAAAAAAAGvo/E4gJzzB97q8/s576/task.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Frankenstein" by James Whale (1931)&lt;/span&gt;&lt;/div&gt;&lt;h2&gt;this is really magic...&lt;/h2&gt;&lt;p&gt;Recently, I found an update of the &lt;a href="http://www.symfony-project.org/plugins/sfTaskLoggerPlugin"&gt;sfTaskLoggerPlugin&lt;/a&gt;. As the description says, the plugin &lt;i&gt;allows you to run custom tasks and store the results&lt;/i&gt;. In fact, this is a highly customizable tool that provides you monitoring all cron tasks, checking their performance (objects processed, running time) and so on. Installing and configuring this plugin in my company CRM was one of the most challenging and most interesting things I have done since many months.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;few words about cron tasks&lt;/h2&gt;&lt;p&gt;The most important of my projects is a CRM tool that provides some tools for managing an E-commerce company. It is an application that stores lots of data in its own database, but it also has access to several other databases and connects external systems through APIs. Such a complicated system requires several cron tasks (the number is going to be doubled soon). Some of them have to be run once per day, but others have to be run every few minutes. There are few problems you have to face when using cron tasks in a big system:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Running each cron consumes &lt;b&gt;server resources&lt;/b&gt; and estimating the best time period between the cron finishes his task and before he's run again is not easy. If the period is too small, lots of resources will be consumed with no sense (everything depends on the cron, of course), but if the crons are run too rare, other employees' work is a lot more dificult, because their data s not up to date.&lt;/li&gt;&lt;li&gt;Another important thing is &lt;b&gt;task performance&lt;/b&gt; - how fast does it take until the cron finishes his task. When you implement a new task, you measure how long does it take to run the task once. But if your data grows incredibly fast during just few months, will you always remember to check if everything is ok with the application performance?&lt;/li&gt;&lt;li&gt;Finally, you need &lt;b&gt;statistics&lt;/b&gt; to know what is going on in your system - how often a functionality is used, what is the traffic during specific part of the day or for different days of week, etc.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Just one more thing - all this information you would like to know about your own crons should be &lt;b&gt;easily accessible&lt;/b&gt;. Until now, I had a basic logfile system which was really far away from meetig my expectations (look above).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;so, is this plugin useful?&lt;/h2&gt;&lt;p&gt;Extremely! As almost everything in life, the most useful things are usually the easiest. And it's the same right here. But I must admit, that at first sight the plugin's readme seemed complicated - but &lt;i&gt;it's only the first sight&lt;/i&gt; (according to COil, the author of the plugin). In fact, my original task was handled by the plugin after 20 minute. COil replied to my mail within few hours and I got all the answers I needed to install his plugin into my apps.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;few examples of where sfTaskLoggerPlugin is useful&lt;/h2&gt;&lt;p&gt;There are some of my cron tasks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;migrating data between databases&lt;/b&gt;. Different www applications are run independently, each of them having it's own database. It's pretty clear, that an employee won't check several different admin panels each few minutes, so everything has to be in one place. And here comes migrating orders... A customer visits a webpage and submits his order. A system cron is waiting for this to happen and after at most 5 minutes he's run and copies the order data into the CRM database, where all tools to manage this order are available. But what is the time when most orders are submitted? How many, how often? From which of our applications? And how often such cron should be run? And how long does it take...&lt;/li&gt;&lt;li&gt;&lt;b&gt;e-mail sending&lt;/b&gt; - similar as above.&lt;/li&gt;&lt;li&gt;&lt;b&gt;redundant table columns speeding up other functionalities&lt;/b&gt;. In my project I have to generate lots of different XML files for external applications such as price comparators or catalogues. We're using the &lt;a href="http://www.prestashop.com/"&gt;prestashop&lt;/a&gt; to deploy shops. Source prestashop database structure can be highly ineffective in our case, so some product data has to be copied between tables once per day (the ineffective queries are executed only once and the result is stored in the redundant columns which are very easily accessible). And the problem is that it has to be run on all products we have in our database. Running a time-consuming query may be dangerous for performance (it's expected that number of products we have is going to be 4-5 times more that it is now). So I need to watch and check if there's need to divide the process into phases (processing parts of data separately) to prevent a breakdown.&lt;/li&gt;&lt;li&gt;Another thing to look closely at is &lt;b&gt;accessing external applications' WebAPI&lt;/b&gt;. It happens that the WebAPI may be developer-unfriendly :) by providing methods that are really poor. And by the same time, the external application generates great traffic to your company. Well, such integration will be difficult then. Not only you'll have to watch out for lots and lots of traps, problems (and finally - bugs), but also you need to know when to run the cron task and how often. And this is not only about the comfort of other employees' work, but mainly about data consistency, this time. Programming can be art, definitely :).&lt;br /&gt;&lt;/ul&gt;&lt;/p&gt;&lt;h2&gt;main sfTaskLoggerPlugin's features&lt;/h2&gt;&lt;p&gt;Well, it's pretty easy - each cron run is stored in the database. You know &lt;b&gt;the starting and the ending time&lt;/b&gt; of each task (so you know how long does it take to finish the task, how often such task is run, you can check if such task was already run today - and so on). You can define &lt;b&gt;the count of the processed and unprocessed objects&lt;/b&gt; (if any error occurs or if just some amount of data has to be processe later - than you define &lt;b&gt;the id of the last processed object&lt;/b&gt;). You define the &lt;b&gt;error code&lt;/b&gt;, stating if there were any errors during runtime, you're able to check &lt;b&gt;how many crons are running at the moment&lt;/b&gt; (or how many of them has &lt;b&gt;broken&lt;/b&gt; and was never finished). Finally, you define your own &lt;b&gt;comments&lt;/b&gt; for each cron. I use it to generate HTML code that is easily accessible by office workers (in case they need to find if some data was processed and what was the result).&lt;/p&gt;&lt;p&gt;It's easy to display/generate project cron statistics. I'm gonna use &lt;a href="http://www.symfony-project.org/plugins/stOfcPlugin"&gt;stOfcPlugin&lt;/a&gt;, for example, to display how many percent of cron task run migrates any data (and how many just checkes that there is nothing to migrate). There is plenty of examle statistics to generate. I'm gonna provide some real cron examples with potential stats soon...&lt;/p&gt;&lt;h2&gt;why so small popularity?&lt;/h2&gt;&lt;p&gt;To sum up, it's such a shame that there are so many good plugins that are not popular, including &lt;a href="http://www.symfony-project.org/plugins/sfTaskLoggerPlugin"&gt;sfTaskLoggerPlugin&lt;/a&gt;. It's really difficult to break through and make your tool popular in the community. Well, using cron tasks is not the most important symfony feature - but I'm pretty sure that there are more than just 4 users who can make use of logging cron tasks... Or am I wrong? :) &lt;b&gt;Just give this plugin a try!&lt;/b&gt;&lt;/p&gt;&lt;p&gt;By the way, we're looking for a Propel developer who is willing to contribute to the plugin. &lt;i&gt;Any good contribution is welcome&lt;/i&gt;! ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-7065655020762025069?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/7065655020762025069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-crons-and-cron-task-logging.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7065655020762025069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/7065655020762025069'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/09/symfony-crons-and-cron-task-logging.html' title='symfony crons and cron task logging'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-oDS5xpKbno0/TzWeV2dzzDI/AAAAAAAAGvo/E4gJzzB97q8/s72-c/task.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-4584373686928083694</id><published>2010-08-29T13:26:00.000+02:00</published><updated>2012-02-10T20:43:37.030+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>symfony popup with jQuery thickbox - beginner's tutorial</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-nz3VEz0Y7kA/TzVzHfjWGuI/AAAAAAAAGtw/bkzlOQynIhw/s1600/popup.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="338" width="392" src="http://3.bp.blogspot.com/-nz3VEz0Y7kA/TzVzHfjWGuI/AAAAAAAAGtw/bkzlOQynIhw/s400/popup.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "The Jetsons" by Hanna-Barbera (introduced in 1962)&lt;/span&gt;&lt;/div&gt;&lt;h3&gt;Introducing jQuery thickbox pop-up&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;In this tutorial I will show you an easy way to create a thickbox using jQuery thickbox lib. At first, make sure you are familiar with the &lt;a href="http://jquery.com/demo/thickbox/"&gt;thickbox&lt;/a&gt; and take a look at the &lt;a href="http://jquery.com/demo/thickbox/#examples"&gt;examples tab&lt;/a&gt;. We will create our pop-up feature basing on the &lt;b&gt;iFramed Content&lt;/b&gt; section.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Install jQuery thickbox&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;The first thing you need to do is installing the software, of course. I want to make this tutorial as easy as possible, so just run the following commands from the project root directory:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="bash" style="font-family: monospace;"&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;wget&lt;/span&gt; http:&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;//&lt;/span&gt;jquery.com&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;demo&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox-code&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox-compressed.js &lt;span style="color: rgb(102, 0, 51);"&gt;-O&lt;/span&gt; web&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;js&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox-compressed.js&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;wget&lt;/span&gt; http:&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;//&lt;/span&gt;jquery.com&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;demo&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox-code&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox.css &lt;span style="color: rgb(102, 0, 51);"&gt;-O&lt;/span&gt; web&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;css&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox.css&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;wget&lt;/span&gt; http:&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;//&lt;/span&gt;jquery.com&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;src&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;jquery-latest.pack.js &lt;span style="color: rgb(102, 0, 51);"&gt;-O&lt;/span&gt; web&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;js&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;jquery-latest.pack.js&lt;br /&gt;&lt;span style="color: rgb(194, 12, 185); font-weight: bold;"&gt;wget&lt;/span&gt; http:&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;//&lt;/span&gt;jquery.com&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;demo&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;thickbox&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;loadingAnimation.gif &lt;span style="color: rgb(102, 0, 51);"&gt;-O&lt;/span&gt; web&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;/&lt;/span&gt;loadingAnimation.gif&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;After the files are downloaded, you need to make symfony include them into the generated output. One of the possible ways is to edit your &lt;b&gt;application/config/view.yml&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;  &lt;span style="color: blue;"&gt;stylesheets&lt;/span&gt;:    [ ..., thickbox.css ]&lt;br /&gt;  &lt;span style="color: blue;"&gt;javascripts&lt;/span&gt;:    [ ..., jquery-latest.pack.js, thickbox-compressed.js ]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The thickbox is already installed in your symfony project.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Basic usage&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;To make everything elegant, add 2 routes to your &lt;b&gt;application/config/routing.yml&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;index_popup&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;url&lt;/span&gt;:   /popup&lt;br /&gt;  &lt;span style="color: blue;"&gt;param&lt;/span&gt;: { &lt;span style="color: navy;"&gt;module&lt;/span&gt;: main, &lt;span style="color: navy;"&gt;action&lt;/span&gt;: popup }&lt;br /&gt;&lt;span style="color: blue;"&gt;basic_popup&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;url&lt;/span&gt;:   /basic-popup&lt;br /&gt;  &lt;span style="color: blue;"&gt;param&lt;/span&gt;: { &lt;span style="color: navy;"&gt;module&lt;/span&gt;: main, &lt;span style="color: navy;"&gt;action&lt;/span&gt;: basicPopup }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The first route is just a demo action to demonstrate thickbox and you can the index_popup action with the following url:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;http://local_sf_test/popup&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The second route executes an action that shall be displayed inside the popup. Now we shall create the index_popup action inside the &lt;b&gt;application/modules/main/actions/actions.class.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;  * Executes popup action&lt;br /&gt;  *&lt;br /&gt;  * @param sfRequest A request object&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executePopup&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;and a link executing our basic popup - add the following code into your &lt;b&gt;application/modules/main/templates/popupSuccess.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;a class="thickbox" href="&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; url_for&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'@basic_popup'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;?keepThis=true&amp;amp;TB_iframe=true&amp;amp;height=100&amp;amp;width=400"&amp;gt;run basic popup!&amp;lt;/a&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;It's already working - if you press this link in the development mode, you'll get the symfony error &lt;i&gt;Action "main/basicPopup" does not exist.&lt;/i&gt; - but generated in the thickbox. Now we're only left to create this action - create the file &lt;b&gt;application/modules/main/templates/basicPopupSuccess.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;h1&gt;basic popup example&amp;lt;/h1&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;and the last thing - the basicPopup action inside the &lt;b&gt;application/modules/main/actions/actions.class.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;  * Executes basic popup action&lt;br /&gt;  *&lt;br /&gt;  * @param sfRequest A request object&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeBasicPopup&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The logic is very simple - only two things to be done:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The string &lt;b&gt;?keepThis=true&amp;TB_iframe=true&amp;height=100&amp;width=400&lt;/b&gt; is added to the end of the link's href attribute to pass some extra parameters to the thickbox. Those parameters can be easily modified, according to thickbox documentation.&lt;/li&gt;&lt;li&gt;The link has to have the CSS &lt;i&gt;thickbox&lt;/i&gt; class&lt;/li&gt;&lt;/ul&gt;The screenshot below presents the output:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img186/3919/popup1.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As we can see, the web debug toolbar is not fitting well here, therefore we may disable it by adding the following code to the &lt;b&gt;executeBasicPopup&lt;/b&gt; action:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;set&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_web_debug'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This would display the popup without web debug no matter if the production or development controller is running:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img801/707/popup2.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Advanced usage&lt;/h3&gt;&lt;p&gt;Above example could only display some static content. But it's not all that symfony thickbox integration can do - for example, you can embed symfony forms inside a popup. Create new action inside the &lt;b&gt;application/modules/main/actions/actions.class.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;  * Executes advanced popup action&lt;br /&gt;  *&lt;br /&gt;  * @param sfRequest A request object&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeAdvancedPopup&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;set&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_web_debug'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// disable sf_web_debug&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;form&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;new&lt;/span&gt; ExampleForm&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// create the form object&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;isMethod&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'post'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;form&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;bind&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getParameter&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'example_form'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;form&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;isValid&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;// do some business logic&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUser&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setFlash&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'notify'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'this message will be displayed inside the popup'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderPartial&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'main/message'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderPartial&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'example_partial'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;and a new route inside &lt;b&gt;application/config/routing.yml&lt;/b&gt; file, corresponding to the new action:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;advanced_popup&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: blue;"&gt;url&lt;/span&gt;:   /advanced-popup&lt;br /&gt;  &lt;span style="color: blue;"&gt;param&lt;/span&gt;: { &lt;span style="color: navy;"&gt;module&lt;/span&gt;: main, &lt;span style="color: navy;"&gt;action&lt;/span&gt;: advancedPopup }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;update the &lt;b&gt;popupSuccess.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;a class="thickbox" href="&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; url_for&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'@basic_popup'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;?keepThis=true&amp;amp;TB_iframe=true&amp;amp;height=100&amp;amp;width=400"&amp;gt;run basic popup!&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;a class="thickbox" href="&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; url_for&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'@advanced_popup'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;?keepThis=true&amp;amp;TB_iframe=true&amp;amp;height=100&amp;amp;width=400"&amp;gt;run advanced popup!&amp;lt;/a&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now it's up to you to create a form class (the easiest way is to use a model form generated class) and display all its fields inside the &lt;b&gt;_example_partial.php&lt;/b&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="css" style="font-family: monospace;"&gt;&amp;lt;style&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 204);"&gt;#form&lt;/span&gt; &lt;span style="color: rgb(0, 170, 0);"&gt;{&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;background&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(204, 0, 204);"&gt;#d3e5f4&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;padding&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(153, 51, 51);"&gt;5px&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51);"&gt;15px&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;color&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;:&lt;/span&gt;&lt;span style="color: rgb(204, 0, 204);"&gt;#1f3037&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;;&lt;/span&gt;&lt;span style="color: rgb(0, 170, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 128); font-style: italic;"&gt;/* some other CSS to be used by the popup form */&lt;/span&gt;&lt;br /&gt;&amp;lt;/style&lt;span style="color: rgb(0, 170, 0);"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;div id="form"&amp;gt;&lt;br /&gt;  &amp;lt;form action="" method="post"&amp;gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$form&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderHiddenFields&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$form&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'example_field'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;renderError&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;label class="label" for="example_form_example_field"&amp;gt;example label&amp;lt;/label&amp;gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$form&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'example_field'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;render&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;input type="submit" value="submit" /&amp;gt;&lt;br /&gt;  &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The last thing to be created is the file to be used as the message partial, &lt;b&gt;_message.php&lt;/b&gt;:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;span&gt;example message&amp;lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Live app example&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;After clicking this button:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img153/9917/popup6.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;the following popup is displayed:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img409/9792/popup3.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;the form validation errors are displayed:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img693/6726/popup4.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;and finally the submission message is displayed:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;img src="http://a.imageshack.us/img651/7447/popup5.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-4584373686928083694?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/4584373686928083694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/08/symfony-popup-with-jquery-thickbox.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4584373686928083694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/4584373686928083694'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/08/symfony-popup-with-jquery-thickbox.html' title='symfony popup with jQuery thickbox - beginner&apos;s tutorial'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-nz3VEz0Y7kA/TzVzHfjWGuI/AAAAAAAAGtw/bkzlOQynIhw/s72-c/popup.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-1415146760376129644</id><published>2010-08-16T23:52:00.000+02:00</published><updated>2012-01-15T22:16:33.456+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><title type='text'>Embedding videos in symfony projects using sfVideoPlugin</title><content type='html'>&lt;h2&gt;What does the plugin do?&lt;/h2&gt;&lt;br /&gt;&lt;a href="http://www.symfony-project.org/plugins/sfVideoPlugin"&gt;sfVideoPlugin&lt;/a&gt; is a plugin created by a small international symfony developers team. It's destined to give an easy interface for online video embedding. The plugin uses &lt;a href="http://flowplayer.org/"&gt;flowplayer&lt;/a&gt; software and uses files with the &lt;b&gt;flv&lt;/b&gt; extension.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;It's so easy&lt;/h2&gt;&lt;br /&gt;sfVideoPlugin comes provided with few ways of embedding a flash video player inside you project.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;including a partial&lt;/h3&gt;&lt;p&gt;Once the &lt;b&gt;plugin:publish-assets&lt;/b&gt; task has been run, flv files can be accessed from the web. Just include the &lt;i&gt;video&lt;/i&gt; partial from the &lt;i&gt;sfVideo&lt;/i&gt; module (enable it first, of course) passing one obligatory parameter - file (it's taken from the default flv directory):&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;include_partial&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sfVideo/video'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'01.flv'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;Take a look at the plugin &lt;a href="http://symfny.rox.pl/video"&gt;demo site&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;video widget&lt;/h3&gt;&lt;p&gt;Use the sfVideoWidget class inside your forms to display the player inside a form (you may use predefined sfVideoForm class which has only one widget). An example study case using video widget is uploading video files in the backend - user should have the opportunity to display the video file before publishing it online.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;multiple player embedding&lt;/h3&gt;&lt;p&gt;A simple parameter has been added to the partial mentioned above to enable displaying more than one video widget on one page. If the &lt;i&gt;player&lt;/i&gt; parameter is not set when including a partial, the default value is "&lt;i&gt;player&lt;/i&gt;" - you need to override the default value to display more than one player. Put the following code into an action:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;players&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'01.flv'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player01'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'02.flv'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player02'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'file'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'03.flv'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'player03'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;and include the partial for each of defined players:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;foreach&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$players&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$p&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sfVideo/video'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$p&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;endforeach&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;Take a look at a &lt;a href="http://symfony.rox.pl/multi-video"&gt;live demo&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;configuration&lt;/h3&gt;&lt;p&gt;At now, there are four attributes defined in the &lt;b&gt;app.yml&lt;/b&gt; file that are &lt;b&gt;common&lt;/b&gt; for all players in the plugin. These are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;width&lt;/li&gt;&lt;li&gt;height&lt;/li&gt;&lt;li&gt;autoplay&lt;/li&gt;&lt;li&gt;autobuffering&lt;/li&gt;&lt;/ul&gt;The first two attributes take an integer value and the rest takes true/false values. Access them using:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;sfConfig&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;get&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'app_video_autoplay'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;contribution&lt;/h2&gt;&lt;p&gt;Feel free to comment on the post and to contribute to develop the plugin.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-1415146760376129644?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/1415146760376129644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/08/embedding-videos-in-symfony-projects.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/1415146760376129644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/1415146760376129644'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/08/embedding-videos-in-symfony-projects.html' title='Embedding videos in symfony projects using sfVideoPlugin'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-2448129724233801217</id><published>2010-08-08T23:42:00.000+02:00</published><updated>2012-01-15T22:16:20.051+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='mail'/><title type='text'>Mail testing configuration in symfony</title><content type='html'>&lt;p&gt;By default, the symfony mail delivery strategy is set to &lt;i&gt;none&lt;/i&gt;. That means, that calling &lt;b&gt;send&lt;/b&gt; method upon &lt;b&gt;sfMailer&lt;/b&gt; object will perform no action.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Configuring mail delivery_strategy&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;All possible delivery strategies are described in the &lt;a href="http://www.symfony-project.org/gentle-introduction/1_4/en/11-Emails#chapter_11_the_delivery_strategy"&gt;symfony docs&lt;/a&gt;. A good solution is to edit &lt;b&gt;factories.yml&lt;/b&gt; in all application config directories and set production environment to &lt;i&gt;realtime&lt;/i&gt; and development environment to &lt;i&gt;single_address&lt;/i&gt;. The developer enters an E-mail address he's got access to, puts it in the &lt;i&gt;delivery_address&lt;/i&gt; option and all mails sent from the project will be delivered to that address (so there's no worry that a customer/user will receive test E-mail). Put the following lines into &lt;b&gt;factories.yml&lt;/b&gt; file to define mail configuration:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;prod&lt;/span&gt;:&lt;br /&gt;&lt;span style="color: blue;"&gt;  mailer&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;delivery_strategy&lt;/span&gt;: realtime&lt;br /&gt;&lt;span style="color: blue;"&gt;dev&lt;/span&gt;:&lt;br /&gt;&lt;span style="color: blue;"&gt;  mailer&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;delivery_strategy&lt;/span&gt;: single_address&lt;br /&gt;      &lt;span style="color: blue;"&gt;delivery_address&lt;/span&gt;: your@address.com&lt;/pre&gt;Once we've set those values (even in the very beginning of a project development), we don't have to carry about mail configuration, hence symfony will carry out all mails to the correct addresses when working in the production environment.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-2448129724233801217?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/2448129724233801217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/08/mail-testing-configuration-in-symfony.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2448129724233801217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/2448129724233801217'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/08/mail-testing-configuration-in-symfony.html' title='Mail testing configuration in symfony'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-8112008872802595843</id><published>2010-07-25T23:04:00.000+02:00</published><updated>2012-01-15T22:22:27.633+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><title type='text'>Default form values for new objects</title><content type='html'>&lt;h2&gt;what for?&lt;/h2&gt;&lt;br /&gt;Sometimes you may need to get some random values when creating a new object from the symfony generated form. This can happen in lots of situations, some of them are listed below:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;u&gt;populating article comments in a community website&lt;/u&gt; - a community website looks a lot better when each article has at least several comments. So when an article is created, few comments need to be created right afterwards. Choosing random names is quite easy, of course, but what if your system allows only logged in users to leave comments (which means, comment table row does not have author string value, but author_id integer foreign key)? In such case you have to look up a random user id in the database, which is pretty impossible. Default form values to the rescue!&lt;/li&gt;&lt;li&gt;&lt;u&gt;E-shop product attributes&lt;/u&gt; - each product has some attributes that measure its quality, just like reliability, aesthetics, performance and so on. As we know, many information in advertisement is pure bull*hit nowadays, e.g. values of product attributes are probably fabricated. Suppose there are many attributes for each product (available inside the form or inside an embedded form, it doesn't matter). Defining each attribute costs time and an E-commerce shop employee will work slower if he needs to input each value separately. Again, default form values comes with assistance!&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;solution&lt;/h2&gt;&lt;p&gt;Put the following code into the &lt;b&gt;setup&lt;/b&gt; or &lt;b&gt;configure&lt;/b&gt; method of a form class:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;isNew&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 136);"&gt;$this&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;setDefault&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'name'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; Tools&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getRandomName&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Above feature is really easy to implement and you'll find it really useful when generating some partially random data. Of course, you may also set random values after the form is submitted, when a form field is simply disabled - but then you don't have a posibility to change it during object creation.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-8112008872802595843?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/8112008872802595843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/07/default-form-values-for-new-objects.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8112008872802595843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8112008872802595843'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/07/default-form-values-for-new-objects.html' title='Default form values for new objects'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-5851851886232751828</id><published>2010-07-21T20:25:00.000+02:00</published><updated>2012-02-10T21:54:13.462+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Advanced SQL expressions in Doctrine</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MjVza9QiQMg/TzWD2BAu4CI/AAAAAAAAGt8/lPJ5Je2PoWg/s1600/advanced_sql_expressions.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-MjVza9QiQMg/TzWD2BAu4CI/AAAAAAAAGt8/lPJ5Je2PoWg/s576/advanced_sql_expressions.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "Irma la Douce" by Billy Wilder (1963)&lt;/span&gt;&lt;/div&gt;&lt;h2&gt;missing element in symfony documentation&lt;/h2&gt;&lt;p&gt;&lt;i&gt;Symfony and Doctrine book&lt;/i&gt; (&lt;a href="http://www.symfony-project.org/doctrine/1_2/en/06-Working-With-Data"&gt;chapter 6&lt;/a&gt;) describes DQL API, but one very important SQL feature is missing: &lt;u&gt;advanced expressions&lt;/u&gt;. Particularly, you may often need to use &lt;u&gt;advanced logical expressions in &lt;i&gt;WHERE&lt;/i&gt; clause&lt;/u&gt;.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;example&lt;/h2&gt;&lt;p&gt;For example, we run a cron task searching for all active posts which does not meet &lt;u&gt;all SEO requirements&lt;/u&gt; - then a warning mail is sent to a particular employee of a company to do something with it. So the query needs to look for Post objects:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Post p'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;/pre&gt;which are active:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'p.active = 1'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;/pre&gt;and have invalid SEO data at the same time, let's assume that SEO is invalid when at least one of all SEO data columns is empty (title, keywords and description):&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.meta_description) = 0'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.meta_keywords) = 0'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;orWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.meta_title) = 0'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;Now take a look at the above code - is that correct? Of course not! We want to generate the following query:&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SELECT&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;*&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;FROM&lt;/span&gt; Post p&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;WHERE&lt;/span&gt; p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;active &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;AND&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;br /&gt;  LENGTH&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;meta_description&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;OR&lt;/span&gt; &lt;br /&gt;  LENGTH&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;meta_keywords&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt; &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;OR&lt;/span&gt; &lt;br /&gt;  LENGTH&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;p&lt;span style="color: rgb(102, 204, 102);"&gt;.&lt;/span&gt;meta_title&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;0&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;/pre&gt;Three SEO alternatives need to be enclosed in parenthesis. But Doctrine Query API does not provide specific methods doing that. Fortunately, we may use standard query methods (&lt;i&gt;where&lt;/i&gt;, &lt;i&gt;orWhere&lt;/i&gt;, &lt;i&gt;andWhere&lt;/i&gt;, etc.). Unfortunately, we can use them only on the top-level of the query (meaning that all we write stays outside parenthesis). So the top-level of query is created by two arguments linked with &lt;b&gt;AND&lt;/b&gt; logical operator - each of those arguments use one DQL API &lt;i&gt;where&lt;/i&gt; method. But the second argument (invalid SEO) is internally ivided into an alternative of three subarguments, using &lt;b&gt;OR&lt;/b&gt; logical operator. The final query looks like:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$objects&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;from&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Post p'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;where&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'p.active = 1'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;andWhere&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.link_rewrite) = 0 OR '&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.meta_description) = 0 OR '&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'LENGTH(p.meta_keywords) = 0 OR '&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;execute&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Anyway, it works. Maybe the Doctrine API will be more friendly in Symfony 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-5851851886232751828?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/5851851886232751828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/07/advanced-sql-expressions-in-doctrine.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5851851886232751828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/5851851886232751828'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/07/advanced-sql-expressions-in-doctrine.html' title='Advanced SQL expressions in Doctrine'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-MjVza9QiQMg/TzWD2BAu4CI/AAAAAAAAGt8/lPJ5Je2PoWg/s72-c/advanced_sql_expressions.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-1356945129418508276</id><published>2010-06-25T00:16:00.000+02:00</published><updated>2012-01-15T22:20:27.486+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Using SQL built-in functions in doctrine queries</title><content type='html'>This short article describes a small trick that enables using SQL built-in functions inside doctrine queries. The trick is to use ticks inside the query.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;example&lt;/h2&gt;&lt;br /&gt;We want to update all records of a table by setting one of its column to be rounded to 2 decimal points. By default, doctrine will ignore &lt;b&gt;2&lt;/b&gt; sign which is after the comma inside the &lt;b&gt;ROUND&lt;/b&gt; function.&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;update&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Product'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;set&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'feature_b'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'ROUND(feature_a, 2)'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;will generate the following query:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;UPDATE&lt;/span&gt; product &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SET&lt;/span&gt; feature_b &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; ROUND&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;feature_a&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;which is NOT what we want. We only need to add ticks surrounding the value to be rounded:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(177, 177, 0);"&gt;return&lt;/span&gt; Doctrine_Query&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;create&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;update&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Product'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;set&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'feature_b'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'ROUND(`feature_a`, 2)'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;and the generated query will satisfy our needs:&lt;br /&gt;&lt;br /&gt;&lt;pre class="sql" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;UPDATE&lt;/span&gt; product &lt;span style="color: rgb(153, 51, 51); font-weight: bold;"&gt;SET&lt;/span&gt; feature_b &lt;span style="color: rgb(102, 204, 102);"&gt;=&lt;/span&gt; ROUND&lt;span style="color: rgb(102, 204, 102);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`feature_a`&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(204, 102, 204);"&gt;2&lt;/span&gt;&lt;span style="color: rgb(102, 204, 102);"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-1356945129418508276?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/1356945129418508276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/06/using-sql-built-in-functions-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/1356945129418508276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/1356945129418508276'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/06/using-sql-built-in-functions-in.html' title='Using SQL built-in functions in doctrine queries'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-8358810125505833529</id><published>2010-05-19T08:11:00.000+02:00</published><updated>2012-02-10T18:12:45.139+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><title type='text'>Multiple database symfony configuration (doctrine)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-L2P248KkczQ/TzUcW4e3a8I/AAAAAAAAGsA/jjuPcwqy2Xc/s1600/platoon.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-L2P248KkczQ/TzUcW4e3a8I/AAAAAAAAGsA/jjuPcwqy2Xc/s576/platoon.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from ingenious "Platoon" by Oliver Stone (1986)&lt;/span&gt;&lt;/div&gt;It may happen that we'll need to connect to many databases inside one project. As this problem is not very common, I'll try to present the easiest way to manage multiple database connections.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;First of all, edit the &lt;b&gt;databases.yml&lt;/b&gt; file and set all database connections with appropriate labels. This means, the &lt;i&gt;doctrine&lt;/i&gt; connection label means nothing and therefore it should be changed. Usually, in such case, apart from all external databases, the project itself has its own database which connection to is called &lt;i&gt;master&lt;/i&gt;. Below is an example of multiple connection project databases.yml file:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;  master&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;class&lt;/span&gt;: sfDoctrineDatabase&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;dsn&lt;/span&gt;:      mysql:host=localhost;dbname=admin&lt;br /&gt;      &lt;span style="color: blue;"&gt;username&lt;/span&gt;: admin&lt;br /&gt;      &lt;span style="color: blue;"&gt;password&lt;/span&gt;: Mt5iA0Lcm0&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;production&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;class&lt;/span&gt;: sfDoctrineDatabase&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;dsn&lt;/span&gt;:      mysql:host=localhost;dbname=old_shop&lt;br /&gt;      &lt;span style="color: blue;"&gt;username&lt;/span&gt;: shop&lt;br /&gt;      &lt;span style="color: blue;"&gt;password&lt;/span&gt;: Mt5iA0Lcm0&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;shop_one&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;class&lt;/span&gt;: sfDoctrineDatabase&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;dsn&lt;/span&gt;:      mysql:host=localhost;dbname=shop_one&lt;br /&gt;      &lt;span style="color: blue;"&gt;username&lt;/span&gt;: shop&lt;br /&gt;      &lt;span style="color: blue;"&gt;password&lt;/span&gt;: Mt5iA0Lcm0&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: blue;"&gt;shop_two&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: blue;"&gt;class&lt;/span&gt;: sfDoctrineDatabase&lt;br /&gt;    &lt;span style="color: blue;"&gt;param&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: blue;"&gt;dsn&lt;/span&gt;:      mysql:host=localhost;dbname=shop_two&lt;br /&gt;      &lt;span style="color: blue;"&gt;username&lt;/span&gt;: shop&lt;br /&gt;      &lt;span style="color: blue;"&gt;password&lt;/span&gt;: Mt5iA0Lcm0&lt;/pre&gt;&lt;br /&gt;This is an example database list of a project that migrates all data from one shop (which is, for example, too old and too bad to be mantained anymore) into two new distinct shops (each shop is deployed using open source software, like magento or prestashop) and one admin database (which is created for the project itself).&lt;br /&gt;&lt;br /&gt;Now we need to apply a small change to the schema.yml files:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: blue;"&gt;connection&lt;/span&gt;: master&lt;/pre&gt;This should be added in the beginning of each schema yml file, defining the connection name. It means, that all models defined in such schema file will be bound to chosen database. Remember to execute the clear cache command, because otherwise you may force difficulties with class files autoload (also when you're using plugins).&lt;br /&gt;&lt;br /&gt;The main feature in connecting different classes with distinct databases is to have &lt;i&gt;class-database&lt;/i&gt; connection binding set properly. In each base class, you will see&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: #666666; font-style: italic;"&gt;// Connection Component Binding&lt;/span&gt;&lt;br /&gt;Doctrine_Manager&lt;span style="color: #339933;"&gt;::&lt;/span&gt;&lt;span style="color: #004000;"&gt;getInstance&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #004000;"&gt;bindComponent&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;'Product'&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: blue;"&gt;'master'&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;&lt;/pre&gt;This line of code states, that all Product objects will be fetched from master database connection.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;the structure to be chosen&lt;/h2&gt;&lt;br /&gt;From this moment, the model classes generated by the framework will include classes from all databases. And now here comes the main question to answer - &lt;i&gt;how complex is my project and do I have to follow all symfony default mechanisms&lt;/i&gt;? Answer to this question is essential, because many implementation solutions will depend on the decision made. I'll briefly describe two alternative approaches:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Stick to the defaults&lt;/b&gt;. Suppose, you'll have about one hundred tables in each database. If we have 4 connections set, it gives 400 distinct model classes (to be precise: 400 base model classes, 400 model classes and 400 table classes, which is 1200).They all should have connection bindings set correctly, anyway, searching through 400 classes in a tree-view may be frustrating - this is the main disadvantage. Another one is that you'll have to generate all classes even if you won't need them (e.g. if you use open source software, you may need only some of them for your project). And one more disdvantage - you'll also have to keep all form and filter classes for all tables even if they're not needed. But the advantage is that if you modify anything in schema.yml file, base classes will be updated automatically and you don't have to care about that. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Choose your own lib directory structure&lt;/b&gt;. The task now is to separate all generate classes into different directories so that everything will be in order. The basic solution is to organise one directory for each database connection. The good things about this solution are: everything is more structured, easier to find; you don't have to keep all classes (if you need only few). And you don't have to keep all model/form/filter classes that doctrine generates - you choose them manually. The disadvantage is that all modifications made in schema files have to be updated manually (replace old version of your base model class in a special directory with a just generated new base model class). &lt;b&gt;Subversion&lt;/b&gt; (or other versioning systems) helps greatly to keep everything up to date and user-friendly. After running &lt;u&gt;symfony doctrine:generate-model&lt;/u&gt; you update the files you want (which means, destination base class files are replaced with their new versions) - then you &lt;u&gt;commit your changes&lt;/u&gt; and afterwards &lt;u&gt;clean it&lt;/u&gt; (remove model directory and update it from repository, so that all files you changed are saved in the repository and all the rest - which you don't want - is deleted).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Although the second option may seem too complicated or weird (or even both at the same time), I definitely prefer it. One of its great advantages I still haven't to mentioned is that it if you use your own lib classes structure, it allows you to do advanced and highly complex solutions (&lt;i&gt;example: you've got few shops powered by the same OS software. And you need one tool to manage them all - an administration application. If you want to follow symfony default mechanisms, you have a very big problem, since table names will surely be the same in different shops. And connection binding is really basic in doctrine, since such problem is really rare. Even if you use distinct prefixes to set table names for distinct shop databases, you'll still force a big problem, since you'll need to copy-paste all methods between analogical classes, let's say, you define &lt;/i&gt;getFullName&lt;i&gt; method in Product class - you'll have to copy this method into XxxProduct, YyyProduct, ZzzProduct and so on, if you want to stick to symfony defaults&lt;/i&gt;. In my opinion it's enough to prove, that symfony defaults are good as long as the project is easy, but if it's really advanced, non-standard solutions are usually the only way). Sticking to symfony defaults and being ready to regenerate model at the same time disables some higly complex features.&lt;br /&gt;&lt;br /&gt;&lt;h2 style="color: red;"&gt;look out for the bug!&lt;/h2&gt;Unfortunately, there's a bug in symfony core, dealing with multiple database connections. It has been reported some time ago on &lt;a href="http://trac.symfony-project.org/ticket/7689"&gt;trac&lt;/a&gt;, however, the bug is still there. In short, in some cases DoctrineManager takes the last connection from the databases.yml list, instead of the one you choose (you can read the details on the ticket page). To avoid problems with it, I pay attention to have &lt;u&gt;all base model classes defined with the correct connection binding&lt;/u&gt; - and this is enough to get all project working.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see, you're already ready to go - your site can handle multiple database connections!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3825636150904136311-8358810125505833529?l=symfony-world.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://symfony-world.blogspot.com/feeds/8358810125505833529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://symfony-world.blogspot.com/2010/05/multiple-database-symfony-configuration.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8358810125505833529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3825636150904136311/posts/default/8358810125505833529'/><link rel='alternate' type='text/html' href='http://symfony-world.blogspot.com/2010/05/multiple-database-symfony-configuration.html' title='Multiple database symfony configuration (doctrine)'/><author><name>Tomasz Ducin</name><uri>http://www.blogger.com/profile/08377176323730229843</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_sCXItTQZ81A/S1si-7wTRGI/AAAAAAAAGgw/iFgSt3vX3f0/S220/mnROjnHBj6jU4CYthUOMelXCjl6s0Fu2wKcdN5IdnKVFq0sC5SjjJ-K9U54gRH2C.jpeg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-L2P248KkczQ/TzUcW4e3a8I/AAAAAAAAGsA/jjuPcwqy2Xc/s72-c/platoon.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3825636150904136311.post-8293755338224783513</id><published>2010-05-14T12:35:00.000+02:00</published><updated>2012-02-10T18:29:15.027+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><title type='text'>Ajax/symfony easy &amp; user friendly example</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-NF_XRhGIovQ/TzUEY21HDbI/AAAAAAAAGrE/t_DY246E5cw/s1600/ajax_example.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-NF_XRhGIovQ/TzUEY21HDbI/AAAAAAAAGrE/t_DY246E5cw/s576/ajax_example.png" /&gt;&lt;/a&gt;&lt;span class="movie"&gt;Scene from "The Wizard of Oz" by Victor Fleming (1939)&lt;/span&gt;&lt;/div&gt;&lt;p&gt;This time I would like to present a piece of code making use of symfony built-in AJAX functionalities. We're going to build a switch for activating/deactivating users in the listing of the sfDoctrineGuardPlugin (should be the same with Propel).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Dependencies&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;We're gonna use two major symfony plugins: &lt;a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin"&gt;sfDoctrineGuardPlugin&lt;/a&gt; and &lt;a href="http://www.symfony-project.org/plugins/sfJqueryReloadedPlugin"&gt;sfJqueryReloadedPlugin&lt;/a&gt;. I'm not going to show how to install plugins here.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Problem description&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;The moderator of a website needs to have a quick access to the &lt;i&gt;is_active&lt;/i&gt; attribute of all users. This means it takes too much time for him to enter the &lt;i&gt;edit form&lt;/i&gt; of each users, change the &lt;i&gt;is_active&lt;/i&gt; property of a user, save changes, go back to the list, then choose another one and so on. Too many times the page has to be reloaded. We need to make a simpler access to this kind of information.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Another smart use of this technique may be enabing/disabling posts/comments in a blog, guestbook, forum entries and many, many more...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Solution&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;First step is to add &lt;i&gt;activate&lt;/i&gt; and &lt;i&gt;deactivate&lt;/i&gt; to object_actions section in the &lt;strong&gt;sfGuardUser/config/generator.yml&lt;/strong&gt;:&lt;br /&gt;&lt;pre class="php"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;generator&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;param&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;config&lt;/span&gt;:&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;list&lt;/span&gt;:&lt;br /&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;object_actions&lt;/span&gt;:&lt;br /&gt;          &lt;span style="color: rgb(0, 0, 255);"&gt;_edit&lt;/span&gt;: ~&lt;br /&gt;          &lt;span style="color: rgb(0, 0, 255);"&gt;_delete&lt;/span&gt;: ~&lt;br /&gt;          &lt;span style="color: rgb(0, 0, 255);"&gt;activate&lt;/span&gt;: ~&lt;br /&gt;          &lt;span style="color: rgb(0, 0, 255);"&gt;deactivate&lt;/span&gt;: ~&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, the &lt;strong&gt;templates/_list_td_actions.php&lt;/strong&gt; has two lines added, one for activating and the other for deactivating the user. But activating an active user is senseless, such as deactivating a non-active user. So we need to display either activate or deactivate user link depending on it's is_active value:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;span id="user_is_active_action_&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;"&amp;gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;if&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getIsActive&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sfGuardUser/ajax_deactivate'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_guard_user'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;else&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sfGuardUser/ajax_activate'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_guard_user'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;endif&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/span&amp;gt;&lt;/pre&gt;&lt;br /&gt;Now, we put above code into the &lt;strong&gt;_ajax_main_active.php&lt;/strong&gt; partial. &lt;strong&gt;_list_td_actions&lt;/strong&gt; template should look like this now:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;td&amp;gt;&lt;br /&gt;  &amp;lt;ul class="sf_admin_td_actions"&amp;gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$helper&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;linkToEdit&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'params'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt;   &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'class_suffix'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'edit'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'label'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Edit'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$helper&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;linkToDelete&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'params'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt;   &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'confirm'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Are you sure?'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'class_suffix'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'delete'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;'label'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'Delete'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; include_partial&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'ajax_main_active'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'sf_guard_user'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;  &amp;lt;/ul&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;/pre&gt;&lt;br /&gt;And now, create those two templates, &lt;strong&gt;sfGuardUser/templates/_ajax_deactivate.php&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;li class="sf_admin_action_deactivate_user" id="ajax_deactivate_&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;"&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; use_helper&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'jQuery'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; jq_link_to_remote&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;__&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Deactivate'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'sf_admin'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'update'&lt;/span&gt;   &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'user_is_active_action_'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'url'&lt;/span&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'@ajax_sf_guard_user_deactivate?id='&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'script'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'complete'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; jq_remote_function&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'update'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'user_is_active_column_'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'url'&lt;/span&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'graphics/empty'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'script'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;sfGuardUser/templates/_activate.php&lt;/strong&gt; is very similar:&lt;br /&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&amp;lt;li class="sf_admin_action_activate_user" id="ajax_activate_&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; &lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;"&amp;gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; use_helper&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'jQuery'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; jq_link_to_remote&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;__&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'Activate'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'sf_admin'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'update'&lt;/span&gt;   &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'user_is_active_action_'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'url'&lt;/span&gt;      &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'@ajax_sf_guard_user_activate?id='&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'script'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;'complete'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; jq_remote_function&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt; &lt;a href="http://www.php.net/array"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'update'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'user_is_active_column_'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$sf_guard_user&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getId&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'url'&lt;/span&gt;    &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;'graphics/tick'&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span style="color: rgb(0, 0, 255);"&gt;'script'&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0); font-weight: bold;"&gt;true&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Seems quite a lot of templates, uh? This part is the most difficult one, since all parameters have to be set correctly. Software, such as &lt;a href="http://getfirebug.com/"&gt;firebug&lt;/a&gt; are extremely helpful, making it easy to spot any errors, mistakes, typos, etc.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The &lt;i&gt;update&lt;/i&gt; parameter defines the id of the tag that content is going to be changed (when the AJAX action is performed). &lt;i&gt;url&lt;/i&gt; option defines the url of the actions that is going to be performed. &lt;i&gt;complete&lt;/i&gt; option defines what is going to be executed after the main action is completed.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Aditionally, graphics module is added inside the project (but this can be done in many many different ways). Graphics/tick action shows a tick icon and nothing more. The action code:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;  * Displays tick image.&lt;br /&gt;  *&lt;br /&gt;  * @param sfRequest $request A request object&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeTick&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;and the template code:&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;&amp;lt;?php&lt;/span&gt; &lt;span style="color: rgb(177, 177, 0);"&gt;echo&lt;/span&gt; image_tag&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'/sfDoctrinePlugin/images/tick.png'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In the admin generators, I miss a possibility to set a custom object action as a partial (e.g. _object_action_one.php) - the only way to edit them is to override the _td_actions.php file from cache and replace custom object actions with your own code.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The main actions the are going to perform activating and deactivating users shall be defined in the &lt;strong&gt;routing.yml&lt;/strong&gt;:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;ajax_sf_guard_user_activate&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;url&lt;/span&gt;:   /ajax_user_activate/:id&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;param&lt;/span&gt;: { &lt;span style="color: rgb(0, 0, 255);"&gt;module&lt;/span&gt;: sfGuardUser, &lt;span style="color: rgb(0, 0, 255);"&gt;action&lt;/span&gt;: activate }&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;requirements&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;id&lt;/span&gt;: \d+&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;ajax_sf_guard_user_deactivate&lt;/span&gt;:&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;url&lt;/span&gt;:   /ajax_user_deactivate/:id&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;param&lt;/span&gt;: { &lt;span style="color: rgb(0, 0, 255);"&gt;module&lt;/span&gt;: sfGuardUser, &lt;span style="color: rgb(0, 0, 255);"&gt;action&lt;/span&gt;: deactivate }&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;requirements&lt;/span&gt;:&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;id&lt;/span&gt;: \d+&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;... and in the &lt;strong&gt;sfGuardUser/actions/actions.class.php&lt;/strong&gt; file:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="php" style="font-family: monospace;"&gt;&lt;span style="color: rgb(153, 0, 153); font-style: italic;"&gt;/**&lt;br /&gt;   * Activates a user from admin generator list using AJAX.&lt;br /&gt;   *&lt;br /&gt;   * @param sfWebRequest $request&lt;br /&gt;   * @return Partial - generated partial enabling user deactivating (switch).&lt;br /&gt;   */&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;function&lt;/span&gt; executeActivate&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;sfWebRequest &lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 0, 136);"&gt;$user&lt;/span&gt; &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; sfGuardUserTable&lt;span style="color: rgb(51, 153, 51);"&gt;::&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getUserByIdQuery&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 136);"&gt;$request&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: rgb(0, 64, 0);"&gt;getParameter&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;'id'&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="co
