Nerds who love the symfony-project
21 Feb
Scott Meves points me to this presentation by Kris Wallsmith. Lots of information about how to scale up Symfony, and a plugin is thrown in for handling multiple database connections. I’ve not yet dealt with a site on that scale, but this looks like a very promising way to scale up, whenever I’m confronted by that kind of demand.
4 Dec
This tip is a quick one for newbies. The Symfony book has some great tips as to when you would want to use a Symfony forward, vs a Symfony redirect. This quick post will show you the difference between the two and give you some guidelines to know when to use redirect or forward.
So what’s the main difference?
Symfony Redirect: This simply does a HTTP header(”location: “)
Symfony Forward: This is complete custom code that comes with the Symfony framework that forwards you within the Symfony application.
Use Symfony Forward if:
Use a Symfony Redirect if:
Conditional Forwarding/redirect
Quite often you need to forward or redirect if a condition has been met. Be sure to checkout the other Symfony functions that help you do this (forwardIf(), forwardUnless(), forward404If(), forward404Unless(), redirectIf(), and redirectUnless())
What about AJAX calls?
You can check if a HTTP request is an AJAX call before deciding what to do with it by calling calling $request->isXmlHttpRequest() in your actions class. Once you have done this you can choose what you want to do; redirect or forward.
15 Sep
We came across an interesting problem today when setting up an application we’d built earlier in a fresh dev environment to add some features…
Because we’re big fans of MySQL Workbench we made our initial schema changes there, generated the SQL to update the DB, then used a symfony propel:build-schema to generate an updated schema.yml followed by a symfony propel:build-model to update the model…
All good so far, until I began work on the first change and tried to fire off the task I’d just written…
Fatal error: Class 'BaseSMMConfig' not found in /usr/local/projects/smm/lib/model/SMMConfig.php on line 3
After some looking around, I realised my base class was called BaseSmmConfig - spot the problem? Yes, the ‘mm’ was lower case, while my class was looking for ‘MM’ in capitals…
So what caused this?
The application had originally been created by writing the schema.yml file (including the phpName being specified) then doing a symfony propel:build-all to create the DB and the model together. This is fine as the capitalisation used in the hand written schema.yml flowed through to the model. When I had done the reverse, creating a schema.yml from the DB, all it has to go on is the names of the tables, using camel case to identify where an underscore exists in the table name, so the ’smm_config’ table becomes SmmConfig in the schema.yml and model, not SMMConfig as originally typed. Because your extendable model classes don’t get updated (so as not to overwrite your changes) your app then breaks down.
So the lesson:
19 Jun
The guys at UI Studio have done a really nice job of publishing http://symfony-check.org .
It’s a simple site that goes through and helps you check if your symfony application is ready for deploymen. Be sure it check it out.
5 May
This is a quick tip that will hopefully save you some time. The sfFormExtraPlugin is an excellent plugin with lots of extra features to help you build your forms. This tip is regarding the sfWidgetFormJQueryDate widget. This Widget lets you create a jQuery date selector. Setting up this widget is simple, but not well documented. Here are the basic steps of getting this started in your project forms:
1. Install the sfFormExtraPlugin
./symfony symfony plugin:install sfFormExtraPlugin
2. Install relevant jQuery libraries:
a) Download jQuery AND
b) Download jQueryUI
3. Setup jQuery in your project
Extract the JavaScript libs to your project js folder, then modify your app view.yml to include them:
javascripts: [jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js]
Note: The order in which the jQuery libs are included are important and can cause a conflict if they are not in the order above.
4. Setup the CSS for jQuery UI
When you download the jQuery UI, extract the smoothness theme into your web css directory. IE:
/web/css/smoothness
Now include the relevant CSS in your app view.yml:
stylesheets: [main, smoothness/jquery-ui-1.7.1.custom.css]
5. Setup the Widget your form class:
Note in my example below, I will have an image icon as the date selector (/images/icons/calendar_view_month.gif). This is what the form class will look like:
class myForm extends sfForm { public function configure() { $this->setWidgets(array( 'from_date' => new sfWidgetFormJQueryDate(array( 'image'=>'/images/icons/calendar_view_month.gif', 'format' => '%day%/%month%/%year%') ), //...other widgets )); $this->widgetSchema->setLabels(array( 'from_date' => 'From Date', //...other labels )); } }
6. Display it in your view:
Action:
public function executeSearch(sfWebRequest $request){ $this->form = new myForm(); return sfView::SUCCESS; }
View:
.... echo $form['from_date']->renderLabel().":".$form['from_date']; ....
And that’s it! You should get something looking like this:

Hope this helps.
23 Apr
In general, you will always run into issues trying to use the ‘/’ character as part of a parameter in your URL in web development. Recently I’ve run into issues trying to pass a parameter in my URL that has the forwardslash character. For example - trying to pass a URL within a URL:
mymodule/myaction/url=http://google.com
In the case above, Apache will return a 404 as it cannot find that URL (it things that http://google.com is part of the URL).
This is a known issue that can be resolved in two ways:
1) urlencode() + ApacheEncodedSlashes
You could use urlencode() to escape your http:// slashes, and then change you’re ApacheEncodedSlashes directive to allow this (further reading). However this does require a Apache change.
2) The quick fix is to simply tell Apache that it is a parameter, not part of the URL, by changing the / to a ?
mymodule/myaction?url=http://google.com
This works fine. However, in Symfony you can’t get this to work if you are trying to use the link_to_remote Ajax Helper function.
The following code:
$url = "http://google.com"; echo link_to_remote($topic->getName(), array( 'update' => array('success' => 'topic_detail', 'failure' => 'topic_detail_err'), 'url' => "mymodule/myaction?t="$url, 'script' => 'true', 'loading' => visual_effect('appear', 'loading_animation'), 'complete' => visual_effect('appear', 'topic_detail') ));
Will produce this URL:
....mymodule/myaction/url=http://google.com
Notice that Symfony converts the ? to a /. This is because we are using link_to_remote. link_to_remote goes through the routing layer that converts all ? to / characters. If we were using url_for, this would not be an issue.
So how do we overcome this problem if we are using link_to_remote? Well it’s simple - use both the Symfony url_for() helper function as well as the PHP http_build_query function. The http_build_query function encodes the URL for us (so ‘/’ get converted to %2F, alongside other characters).
So the end result looks like this:
$url= url_for("mymodlue/myaction")."?".http_build_query(Array("t"=>$topic->getName())); echo link_to_remote($topic->getName(), array( 'update' => array('success' => 'topic_detail', 'failure' => 'topic_detail_err'), 'url' => $url, 'script' => 'true', 'loading' => visual_effect('appear', 'loading_animation'), 'complete' => visual_effect('appear', 'topic_detail') ));
This forces link_to_remote to use the ? instead of replacing it with a /. Hope this helps!
6 Mar
If you are defining your schema.yml and have a field that is a decimal value, you will find you will need to somehow pass through the precision (maximum number of digits to the left of the point) and the scale (total number after the decimal point). The documentation for the syntax of this is quite poor.
For all those that want to know, in Symfony 1.0 this is how you would define a decimal:
my_decimal: { type: decimal, size: 8,3 }
For Symfony 1.1+, the Syntax is a bit different:
my_decimal:
type: decimal
size: 8
scale: 3
Where 8 is the precision and 3 is the scale. Hope this helps.
6 Mar
Symfony application configuration can be configured for each application in the app.yml file. One of they key problems with this is if you want an end-user to be able to change some of this application configuration, they can’t. You would need to do that for them.
A good way to fix this is to store your applications configuration in the database. This comes with a performance cost (extra calls to your database) - so its up to you to decide if this is the most efficient solution for you.
Here is an outline on how to get started building your application’s config in the database.
Step 1: Define your model
Create the columns you want to store for your application config. In this instance, we are just going to store name and value pairs (ie Attribute & Value). Here is a sample below:
propel: #Application configuration table my_app_config: _attributes: { phpName: MyAppConfig } id: { type: integer, required: true, primaryKey: true, autoIncrement: true } attribute: { type: varchar(255) } value: { type: varchar(255) } ...
Once you have finished that, go ahead and build your model
Step 2: Extend Your MyAppConfig class
So the next step is for us to make it easy to access application configuration. For us to do this, go to your lib/model/MyAppConfig.class.php and extend your base class as follows:
<?php class MyAppConfig extends BaseMyAppConfig { /** * Returns a value of an attribute string for my app's config table * @param string attribute name * @return string The value of that attribute * @author eHabib */ public function lookupValueFromAttribute($attribute){ $c = new Criteria(); $c->add(MyAppConfigPeer::ATTRIBUTE, $attribute); $result = new MyAppConfig(); $result = MyAppConfig::doSelectOne($c); return ($result->getValue()); } }
Step 3: Use it!
Let’s say that in our database we have the following attribute/value paris:
Attribute: app_support_email, Value: myemail@mydomain.com
Attribute: app_base_url, Value: http://whatever
You could access this data in your code by doing this:
$myConfig = new MyAppConfig(); $appEmail = $smyConfig->lookupValueFromAttribute("app_support_email"); $appURL = $smyConfig->lookupValueFromAttribute("app_base_url"); ... echo $appEmail.",".$appURL; //lets print it
That’s it!
Step 4: Configure it via your front-end
The last step (if you wish) is to allow the end-user to update the value of these fields. To do this, you can build a form to update these fields, or use Symfony’s admin generator.
6 Mar
One of the things that might not be clear to Symfony developers is when to use app.yml for your application config and when to use project-level configuration for all your applications.
If your configuration parameter is for all your applications you should place this configuration setting within your config/ProjectConfiguration.class.php (Symfony 1.2.x). This will save you duplicating the config within each app’s app.yml and you only have to specify it once.
Setting up project-level config
You can set project-wide config by editing this file.
.... class ProjectConfiguration extends sfProjectConfiguration { public function setup() { //In my example below I want to tell my app if it should use a proxy or not sfConfig::set('use_proxy', '1'); //1 = True, 0=False $this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin')); } }
Anything you place in your project-level config can be accessed from any application (or Symfony task) by using the standard sfConfig::get() static method.
Note: You would normally have to get the application context if you want to read an application config within a Symfony Task. In this case, you wouldn’t because the config is set at a project level.
19 Feb
In previous Symfony versions it was quite difficult and painful to link your applications together (eg frontend and backend).
Yesterday the Symfony crew posted a tutorial on how easy it is in Symfony 1.2. In essence, its a simple config change and a change to your sfApplicationConfiguration class.
However, this method does still require an absolute hard-code of your application URL within your class (or you could put it in a config setting in your app.yml and read it off there). Even though it required some hard-coding, it still is much simpler and easier to use than Symfony 1.0 and 1.1 methods.
For more information - check out the Symfony blog post.
Symfony nerds tip: To avoid hard-coding as much as possible, you could in your app.yml define your application URL’s for each environment (eg. DEV, TEST and PROD). Once you have, in your application configuration class (which extends sfApplicationConfiguration), you could read the config variable for your application URL, but automate that via sfConfig::get(’sf_environment’). And depending on what environment you are in, you will select the application URL that corresponds to that environment.