What are they Allowable Values in a Symfony 2 Currency Field Type?

500-leonesI love Symfony 2, don’t get me wrong, but the documentation? Lacking.

I know the documentation is always improving, and that essentially no one likes to document when they could be coding, AND that they are always asking for volunteers to help improve the documentation.

The thing is, how do you know what documentation is missing, until you stumble across it during your day-to-day Symfony-ising?

Well, today was one of those days.

I just happened to be using the Money field type for first time ever. And I wanted a few different currency symbols to be made available to my end users.

All good?

Well, not quite.

The documentation lists the default option of Euro. But as we all know, the UK will never enter the Euro. At least, not on my watch.

But what other values are there?

Well, GBP seemed like a good choice. And it’s there. Great.

And there are a few hundred or so more. But where to find them?

Try here.

Just look at that path, Christ on a bike.

Still, at least now you can count all the Albanian Lek your users can throw at you.

How to use Raw SQL Queries in Symfony 2

hashtag-doctrine-dogSometimes, usually when you first start with Symfony 2 (but there are other times too), you just want to get access to good old raw SQL.

I have experimented with a few different ways, and – as with many Symfony issues – the documentation is either shonky, or worst, so cryptic it requires a Mensa-like IQ level to decode just WTF these guys are talking about.

Now, if you are new to Symfony 2, before you go about using raw SQL for everything, do yourself a favour and make sure you learn Doctrine.

And then only if you absolutely must go native SQL, then use the following:

    public function foobar($foobar)
    {
      $stmt = $this->getEntityManager()
                   ->getConnection()
                   ->prepare('SELECT COUNT(id) AS num, foo FROM bar WHERE foobar = :foobar GROUP BY foo');
      $stmt->bindValue('foobar', $foobar);
      $stmt->execute();
      return $stmt->fetchAll();
    }

I love this, and I have used it with great success!, but the credit is not mine, it belongs to a user called althaus on the old symfony forums.

How to render just the CSRF token in Symfony 2

forged-moniesIt’s not often – thankfully – that I need to customise a form to the extent where I can’t use the lovely {{ form_rest(myForm) }} functionality, but when that situation arises, and you still need the CSRF token, you may think you need to go into your form type and add it in there, in some weird hidden field.

The manual page is quite deceptive in that it helps perpetuate this viewpoint.

Thankfully the solution is very simple, simply put: {{ form_row(form._token) }} in your twig template and Symfony’s form creator and rendering processes will handle the rest.

I can’t take the credit for this one, so here’s my original source of knowledge.

Trouble moving your Symfony 2 install to a new server?

nail-biting-nerdI just moved my biggest Symfony 2 site to a new server, and in doing so I made a couple of discoveries.

Discovery #1 – that .git folder? Pretty important.

Yeah, I thought I would save myself the megabytes by not uploading the .git folder. Oopsie.

Turns out that composer throws a fit if you don’t. My bad.

Easily rectified, right? Just upload the damn folder. Ooh the megabytes.

Discovery #2 – that vendors folder? Pretty useless.

The megabytes I saved not uploading the .git folder I figured were well spent on uploading the vendors folder.

Nope.

I ended up getting a funky error:

[RuntimeException]
 Failed to clone http://github.com/fabpot/Twig.git via git, https and http protocols, aborting.
- git://github.com/fabpot/Twig.git
 fatal: No such remote 'composer'

When trying to run composer update.

In the end I had to delete the entire vendors folder (sudo rm -rf vendors/) and re-run composer update.

The conclusion? So many wasted megabytes.

But hey, bandwidth is cheap, right?

Setting up a Debian server for hosting a Symfony 2 site with Apache 2

This is more a guide for me than for the Internet at large, so if you do find this, and you find it useful, excellent.

  1. Install to shell
  2. Check network connectivity – ifconfig
  3. su
  4. Edit /etc/apt/sources.list , remove references to CD Rom
  5. aptitude install sudo
  6. add {user} ALL=(ALL) ALL , under the root line
  7. exit
  8. test with sudo apt-get update
  9. sudo apt-get install git curl acl vsftpd
  10. curl -s https://getcomposer.org/installer | php
  11. sudo mv composer.phar /usr/local/bin/composer

How To Use Doctrine Fixtures with Discriminator Maps

my-pet-cat-entityThis is one of those issues where over-thinking the problem is usually the cause of your problems.

When using a discriminator map, for example, if using Single Table Inheritance, your ‘mapped entity’ will be extending a base entity.

For example, we might have the Pet base entity, and the PetCat extended entity.

Inside our fixture, we might do something like this:

namespace MCM\PetBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;

use MCM\PetBundle\Entity\Pet;

class LoadPetCatData extends AbstractFixture implements OrderedFixtureInterface
{
    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        $cat = new Pet();
        
        $cat->setName('Friendly Cat');
        $cat->setFood('Whiskers');

        $manager->persist($cat);

        $manager->flush();
    }

    /**
    * {@inheritDoc}
    */
    public function getOrder()
    {
        return 3; // the order in which fixtures will be loaded
    }
}

But this will throw up an error, as when doctrine tries to execute your SQL, it will be missing the discriminator mapping.

Why?

Well, above on line 7 we are using: use MCM\PetBundle\Entity\Pet;, but we need to use the extended class / entity, so we should be using: use MCM\PetBundle\Entity\PetCat;.

Then instead of instantiating the base class on line 16: $cat = new Pet();, we just instantiate: $cat = new PetCat();, and all our troubles seem so far away.

Hopefully that helps – I found nothing on Google about this when I looked, and it had me scratching my head as to why. But the answer is pretty straightforward once you stop over thinking it.

Change the text of HTML 5 validation messages in Symfony 2

If you want to change the text of the HTML5 validation messages in your Symfony 2 project, you can do it one of two ways.

The controller method:

$builder->add('email', 'email',array(
    'attr'=>array('oninvalid'=>"setCustomValidity('Would you please enter a valid email?')")
));

Or, the Twig template method:

{{ form_row(form.email, { 'attr': {'oninvalid': "setCustomValidity('Please give me a nice email')"} }) }}

Very helpful, and very easy. Thanks to Carlos Granados at StackOverflow for getting me through that the first time.

Symfony 2 Errors and their meanings

Invalid parameter: token tokenName is not defined in the query.

Check your ->setParameter() statements to make sure your tokens (or first part of the setParameter statement) matches the :tokenName you used in your createQuery.

An example:

        $query = $this->getEntityManager()
                ->createQuery('
                    SELECT
                        c
                    FROM
                        MyBigBundle:Cat c
                    WHERE
                        c.petName = :petName
                ')
                ->setParameter( 'peName' , $petName)
        ;

That would throw the error:

Invalid parameter: token peName is not defined in the query.

Because of the typo in the setParameter statement, it should be petName, but I put peName.

It sounds like it should be easy to spot, but when you have a few parameters, or you have been coding for several hours in a row, sometimes it’s easy to miss.