Archive for April, 2008

UTF-8 and strlen()

Trying to find out the length of a string and wondering why the values are often wrong?

UTF-8 characters can be multi-byte, and strlen() returns the length of the string in bytes, which means the string ååå would actually have a “length” of 6.

One solution is to use the multibyte function “mb_strlen” instead, you will need to have PHP compiled with this - but it seems to be a default in later versions.

E.g.

$value = "ÅØÆbob";
echo strlen($value);
// 9
 
echo mb_strlen($value, 'UTF-8');
// 6

I18n is for life (actions), not just for Christmas (templates)

Well, the point is make sure you Internationalise everything, not just the text you have in the templates.

For example, when using ajax calls you may be rendering text directly from actions, or you may be throwing exceptions which have meaningful error messages which are displayed by the template. You need to remember to “i18nalise” this text too…

From an action, you can access the i18n function via the context singleton, as documented by the Symfony docs (http://www.symfony-project.org/book/1_0/13-I18n-and-L10n)

$this->getContext()->getI18n()->__("yourtexthere");

Remember to do it now, and you won’t kick yourself later!

How to click an image in sfBrowser (symfony lime testing)

This is probably a really simple point, but it actually took me a few searches and tries to find the answer - but it’s quite simple really, just use the image’s alt tag attribute.

If you are using the symfony image_tag helper and not specifying your own alt attribute, then it will be the image name minus the extension, for example - if your template contains this link:

<?php echo link_to(image_tag("fred.jpg"), "@somewhere")) ?>

then in your Functional test, use:

$b->click("fred");

When the pager_navigation function does not create the correct link…

If you have used a route name in the call to this function, it will be parsed based on your routing.yml file, this means that if you don’t have a :page variable listed (and you probably don’t) the route will ignore the page argument that the pager function tries to add.

The easy solution is to add /* to the end of your routing rule, so that any other parameters are allowed.

E.g.

myroute:
  url:   /somewhere/:userid/*
  param: { module: myModule, action: myAction }
 
mynextroute:
  url: etc

Now your routing functions will add any extra parameters as necessary.

Email validator bug

The problem

There is a bug in Symfony’s email validator which means that unless you use both modes (strict and non-strict) invalid email addresses are possible.

Time of writing we are at version 1.0.13 - this could well be (and probably will be) fixed in 1.1 but please let me know if you spot that this has been fixed beforehand.

Strict mode validation

This mode is intended to catch email addresses such as root@localhost, but unfortunately it does not check for valid email strings, so %,%@hotmail.com would be accepted, as well as many other illegal character combinations.

Non-strict mode

This mode checks that the email address contains legal characters, but does not check for internal addresses. This is fine for most cases, but it is worth restricting users from using your site to spam your local mail server.

Solution 1

Sapheriel suggests on his blog that one solution is to override the functionality of the class, and then restore it once an update has been released.

“The best way to achieve this with the least amount of intrusion is to copy sfEmailValidator.class.php into your project’s library folder, modify it, and delete it once a fix has been published”

This may suit many users

Solution 2

If you do not want to worry about something you may have to do in the future, you can also run the validator twice, for example in your validator.yml file:

DoubleCheckEmailValidator:
  class: sfEmailValidator
  param:
    class: sfGuardUser
    column: email
    strict: true
    email_error: This email address is invalid
 
fields:
  email:
    required:
      msg: Please enter an email address
    sfEmailValidator:
      email_error: This email address is invalid
      strict: false
    sfPropelUniqueValidator:
      class: sfGuardUser
      column: email
      unique_error: This email is already in use
    doubleCheckEmailValidator:

You could also write a custom validator which calls the email validator twice, however we have opted for this solution for now.

Thanks to June for the content.

« Previous PageNext Page »