Doctrine postPersist / postUpdate events not firing in Symfony 2?

So let’s say you’ve been tinkering about with the example given on the Symfony 2 manual page for configuring a Doctrine Event Subscriber.

All is good.

Maybe you’ve been through and configured it just like the example, added a subscriber, re-run your fixtures, and everything is tickedyboo.

But then you make a few changes to the subscriber implementation. Maybe it should do something a little differently, and you want to re-save the entity, and get the new implementation to take effect.

Only, it won’t.

You tinker about some more, and everything looks sane. But for some reason, when you go to your form, change nothing, and click the Submit button, the listener just doesn’t seem to take effect.

Strange, eh?

Not exactly.

See, there’s a big ol’ list of lifecycle events that you can hook into, and do funky things with.

But each one has a weird, technical description that doesn’t quite seem to explain what it does in a way that’s easy to comprehend.

If you followed the Symfony documentation example, you might think a postUpdate or postPersist would be triggered whenever you Submit the form. After all, if you stick some debugs in your code, you can see the entity is persisted and the unit of work is flushed.

But yet, your listener doesn’t fire.

Try changing the data in your form, though, and suddenly the listener is triggered.

I’m 100% sure this isn’t a bug. It’s a misunderstanding.

But if you’ve been sat tearing your hair out as to why this damn thing just won’t do your bidding for the last 30 minutes, the only sane solution is to blog about it, and move on.

Hopefully this will save you a headache or two.

#PHPNW2014 Review

Saturday 4th / Sunday 5th October 2014. Manchester. Were you there?

Well, this year I was. I had wanted to go last year, but because I’m a massive noob, I didn’t book a ticket in time. And then they sold out. Such is life.

PHPNW2014 is only the second PHP conference I have ever attendeded. The first, for those interested in such things, was PHPNE2014 (thanks Jeremy!).

The venue was super easy to find – especially with uber-cool satnav Waze. Also, there was a huge multi-story car park about 100 feet away, so aside from their ridiculously small spaces with huge great bollards on either side, just waiting to damage my paintwork, the parking was ample. And at £2 for the entire day, a total bargain.

Saturday

The conference started in the packed main room – an auditorium setting, which with 400+ people packed in, felt a little cramped. However, the mood was vibrant and being that this was a Saturday, you could be fairly certain that the people attending actually care about PHP (and it’s ecosystem), as it was hardly an excuse to skive off the day job. Unless you work Saturdays.

Anthony Ferrara (IrcMaxell) took charge of the opening keynote, and delivered a really interesting presentation. I liked the mentions of Reddit especially – as that’s one of my favourite php communities – even if it can be fairly polarised. I also learned a few things about the history of the PHP community – GoPHP5 for example.

Immediately after the keynote I decided to check out the uncon. This was something I all but skipped at PHPNE, but this time I was determined to experience more of it.

There were some really interesting talks – I managed to get in:

I caught the uncon twice throughout the day, and I really enjoyed every session. Whereas in the main sessions the crowd were more mixed and varied, in the uncon room I got the sense that the skill level of the audience was more intermediate to advanced. I’m not saying that’s where I fit in, but rather, doing a talk to that audience must be different to a main room talk.

Big thanks to PHP East Midland organisers Antonis and Clinton for sorting out the Uncon.

I must comment on a couple of talks I really enjoyed. Firstly, Mike Bell’s talk on mental health in software development took a lot of guts. I also thought he nailed it. Great talk Mike, well done, and I’m thoroughly impressed you decided to do a talk as part of your recovery.

Secondly, Jakub Zalas’s talk on the Dependency Inversion Principle has already helped me improve my own coding. Awesome. And great use of the pebble watch to control the slides.

Just before dinner I caught Making Kanban Work For You by Jez Halford. A great talk to a packed room. Entertaining, interesting, and good use of the kitten pic 🙂 I learned my trello board system is like re-inventing a wheel two clever Japanese guys figured out, documented, and made a system out of many years ago. My trello boards === Kanbanned.

Dinner: was excellent, really nice bit of Salmon and fresh veg. Super surprising at the standard of dinner – and good brain food to boot 🙂

After dinner I checked out Debugging: Past, Present and Future by Derek Rethans. This guy is super, super smart. He invented Xdebug. A little fun trivia – Xdebug dumps are orange because Netherlands. I did not know this. The rest of the talk was highly technical and interesting. It definitely left my mind a little fried though.

The last talk I caught was Implementing Server Side Data Synchronization for Mobile Apps by Michele Orselli. Again, another technical talk – and I have to admit, I couldn’t take it all in. It was interesting, but being the last talk of the day, my mind was already pretty full. Conceptually, it was very cool though and an interesting approach to solving real world problems in a modern PHP & mobile project.

Then I went home… no free bar for me.

Sunday

Sunday started in an interesting fashion. I was late to the party as I had to do some last minute nappy changing on my little girl. Unfortunately this meant I walked in to a hugely packed room where Everzet was giving the presentation I was most looking forward to out of the whole conference. It wasn’t even standing room only – it was maxed out.

So, instead, I went to PHP: Under The Hood by Davey Shafik.

The previous two talks on Saturday had left me fried, but feeling refreshed and raring to go, this talk was perfect. It was indepth, technical, and full of stuff I had never heard of before. So thats how PHP does its magic? Colour me impressed. I loved this one. Nerd out.

Next up was: “Should It?” – A New BDD Tool, Pain Not Included! by Richard McIntyre. Interestingly, this was pitched as an alternative to Behat. And in the room sat Everzet. Creator of Behat. Yikes. Tough crowd. However, the arguments portrayed where well thought out and I could really understand Richard’s points and frustrations. The dialog at the end of the talk between Everzet and Richard was awesome. Everzet is a super smart guy, and one who I have ultimate respect for, so to hear him and Richard debate was brilliant.

Last up for me was The Action-Domain-Responder Design Pattern by Tobias Gies. This is something I am really interested in – and if you are, I recommend this blog post for further reading.

Swag

I collected all kinds of bits and pieces. The Sky Bet stand gave me a big old bag of goodies – usb pens, pads, normal pens, stickers…

Magma came up trumps with a nice yellow screen cloth. Perfect as I keep losing my macbook one.

From inviqa I got an awesome Symfony beanie. Yes! So full of win.

Sponsors

The Sky Bet team stand out. Although I didn’t win their ipad, I did enjoy the banter. Also, the team at Data Sift are doing some interesting things and their product sounds awesome.

The Crowd

A great mix. As I mentioned at the start, the sort of person who attends a programming conference on their weekend must seriously enjoy their craft. And so, the crowd reflected this.

I met some really nice people – hello if you are reading 😉 And had a great time.

Minor niggles

Coffee / tea was not free flowing enough, only at organised breaks. A cup of tea is essential to keep me functional. I know there was a bar, but I’m not ordering tea from a bar like some rambunctious yahoo.

Sunday started too early. 9am starts and a free bar the night before? What is this madness.

tl;dr

It was awesome, see you at #PHPNW2015.

How I fixed exception ‘Bad credentials’ with FOSUserBundle

Waaaa, no fair, unexpected nasty bug message on prod? Boo.

Yup, this one just caught me out – and thankfully my good buddy, brother, and friend managed to pick it up whilst doing some ad-hoc Quality Assurance checks.

Disclaimer: This site may have been in prod, but only just, this was the first release to live 🙂 So no major foul.

Disclaimer part 2: Yes, there is now a passing Codeception acceptance test to make sure this never happens again 🙂

Ok, so this is the bug message (mainly for Google users benefit):

UPDATE `your_table_name` SET exception 'Symfony\Component\Security\Core\Exception\BadCredentialsException' with message 'Bad credentials' in /var/www/html/mysite.dev/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php:73
 Stack trace: #0 /var/www/html/mysite.dev/app/cache/prod/classes.php(120): session_start() #1 /var/www/html/mysite.dev/app/cache/prod/classes.php(198): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() #2 /var/www/html/mysite.dev/app/cache/prod/classes.php(498): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->getBag('attributes') #3 /var/www/html/mysite.dev/vendor/symfony/symfony/src/Symfony/Component/Security/Http/Firewall/ContextListener.php(76): Symfony\Component\HttpFoundation\Session\Session->get('_security_main') #4 /var/www/html/mysite.dev/app/cache/prod/classes.php(2463): Symfony\Component\Security\Http\Firewall\ContextListener->handle(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) #5 [internal function]: Symfony\Component\Security\Http\Firewall->onKernelRequest(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher)) #6 /var/www/html/mysite.dev/app/cache/prod/classes.php(1750): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher)) #7 /var/www/html/mysite.dev/app/cache/prod/classes.php(1683): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) #8 /var/www/html/mysite.dev/app/cache/prod/classes.php(1847): Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) #9 /var/www/html/mysite.dev/app/bootstrap.php.cache(2965): Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) #10 /var/www/html/mysite.dev/app/bootstrap.php.cache(2938): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #11 /var/www/html/mysite.dev/app/bootstrap.php.cache(3087): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #12 /var/www/html/mysite.dev/app/bootstrap.php.cache(2337): Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #13 /var/www/html/mysite.dev/web/app.php(27): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #14 {main}

Lovely job.

Anyway, this was a pretty simple fix, even though there isn’t much about this on Google.

As part of this project, I needed to overwrite the default FOS User Bundle templates with my own. A pretty typical task tbh.

As it happened though, I had removed kept the FOS User Bundle error logic, but removed the translation part.

Something like this:

 {% trans_default_domain 'FOSUserBundle' %}
{% block fos_user_content %} {% if error %}
{{ error.messageKey|trans(error.messageData, 'security') }}
{% endif %}

And I had gone ahead and changed that in my template to something like this:

 {% block content %} {% if error %}
{{ error.messageKey|trans(error.messageData, 'security') }}
{% endif %} {% endblock %}

So I had removed the trans_default_domain, which in turn, was – as far as I can tell – then simply rendering out the full stack trace.

I’m not sure if FOSUserBundle catches that error, and then translates it? That seems kinda unusual to me.

Anyway, hopefully this saves someone some time, someday, some time soon 😉

How to Fix Composer: ErrorException fork failed – cannot allocate memory

If you’re trying to deploy a Symfony project – or Laravel, or pretty much anything using composer – and your deployment server is a little anemic on the memory side of things (Amazon AWS, tiny Digital Ocean droplets, even the basic Linode offerings), then you may well hit an issue when you run composer update during your deploy.

There’s quite a long github issue thread about it, and another one on Stack Overflow.

Anyway, after much frustration, here is my fix – which works for me, hopefully it will work for you too.

This assumes you are developing locally and then deploying to prod using git, which I highly advise. But it will work for any type of deploy if you follow the steps and tweak accordingly.

  1. Do a composer update on your dev box
  2. Commit the updated composer.lock file
  3. Push the commit with the lock file to your prod server (or wherever you’re getting that error)
  4. From the prod server (or wherever), delete your composer cache (rm -rf ~/.composer)
  5. From the prod server (or wherever), delete your vendor folder (rm -rf vendor)
  6. From the prod server (or wherever), run composer install

So, whilst the above is the high level overview, here’s how I did it irl.

  1. Using ssh, I connected to my development virtual machine (VMWare), where from the Symfony root dir (/var/www/html/myproject.dev/), I ran composer update
  2. Wait a while, whilst number 1 finishes.
  3. From my local machine, download the newly updated composer.lock file. Git sees this as a changed file, and so I can then do a git commit on the updated composer.lock file
  4. As I have already set up a git remote for my production server, I can then do a git push for the commit with the lock file to my production server.
  5. When the commit hits the server, the post-receive hook is run automatically, which does all the Symfony deploy stuff like clearing the cache, dumping assets, reinstalling vendors etc.
  6. If all this sounds great, but deploying with Git is something you’re unsure of, I highly recommend this Digital Ocean article, which makes it very easy.

    Hope it helps!