VichUploaderBundle – How to Fix: Cannot Overwrite / Update Uploaded File

this picture of george osbourne has no relevance to this post. i hope it cheered you up.This one stumped me a few days back, and I have had the Chrome tab open ever since to remind myself of how to fix this in future.

The problem: VichUploaderBundle will let you upload a file, but when you go back to the form to edit / update / over-write that file by uploading a new one, it doesn’t upload the new file.

The solution: I cannot take credit for this, as the solution was found by digging around in the github closed issues list for the project, where JMather had posted his working fix.

For those who cannot be bothered to click any of the links I have so helpfully provided, read on.

Make sure you have something like this in your config.yml:

vich_uploader:
    db_driver: orm
    gaufrette: false
    storage: vich_uploader.storage.file_system
    twig: true
    mappings:
        users_uploaded_file:
            delete_on_remove: true
            delete_on_update: true
            inject_on_load: true
            upload_destination: /some/path/to/uploads
            namer: vich_user_upload_file_naming_service

I’m not using Gaufrette for a couple of reasons I won’t go in too. And also, I’m saving the given uploads outside of my Symfony install for security.

The key line is: delete_on_update: true

The other important thing here is you have to have some way of telling your ORM that the file has been updated. This is not immediately obvious, and isn’t documented at all.

So the solution seems to be:

1. Make sure you have at least an updatedAt field in the entity you are uploading too. I would normally have a createdAt and updatedAt field, and use LifecycleCallbacks to update these fields for me on prePersist and preUpdate. This isn’t well documented either in my opinion, so if you are unsure how to use them, please read my post on Lifecycle Callbacks.

2. Then update the method you are using to save the uploaded file to include an updating of the updatedAt property inside your entity. Sounds confusing, so it’s better to explain it with a code snippet:

    public function setUploadedFile($uploadedFile)
    {
        $this->uploadedFile = $uploadedFile;

        if ($uploadedFile instanceof UploadedFile) {
            $this->setUpdatedAt(new \DateTime());
        }
    }

All we are saying here is to set the updatedAt time to now if this is an uploaded file.

This then tells your ORM that the file is new – in a very round the houses kind of way – and correctly uploads the new file. And because we used delete_on_update: true, the old file is deleted so no need to worry about that.

Again, check out the github link if this still doesn’t make sense.

Thanks to Chrysweel for raising this issue, and to JMather for solving it.

Using LifecycleCallbacks for CreatedAt and UpdatedAt in Symfony 2

It's a life cycle. *Tumbleweed*

[Update: May 2015 – This post has been updated with videos]

Lifecycle Callbacks are a super helpful bit of code that I use in a good number of my entities.

They are scary sounding and the documentation on the Symfony 2 official docs doesn’t give a detailed enough demonstration (in my opinion) to explain to the new Symfony user how useful they are.

So, rather than waffle on, I will give a bit of handy code that you can steal and re-use.

namespace MCM\MyExampleBundle\Entity;

// some use statements here

/**
 * MyPretendEntity
 *
 * @ORM\Table(name="my_table_name")
 * @ORM\Entity(repositoryClass="\MCM\MyExampleBundle\Repository\MyPretendRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class MyPretendEntity
{
    // snip snip snip

    /**
     * created Time/Date
     *
     * @var \DateTime
     *
     * @ORM\Column(name="created_at", type="datetime", nullable=false)
     */
    protected $createdAt;

    /**
     * updated Time/Date
     *
     * @var \DateTime
     *
     * @ORM\Column(name="updated_at", type="datetime", nullable=false)
     */
    protected $updatedAt;

    // snip snip snip

    /**
     * Set createdAt
     *
     * @ORM\PrePersist
     */
    public function setCreatedAt()
    {
        $this->createdAt = new \DateTime();
        $this->updatedAt = new \DateTime();
    }

    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set updatedAt
     *
     * @ORM\PreUpdate
     */
    public function setUpdatedAt()
    {
        $this->updatedAt = new \DateTime();
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
}

I have seen this done other ways – some people use only one method for both.

The implementation is up to you – but do remember to use the correct annotations – @ORM\HasLifecycleCallbacks() , @ORM\PrePersist , and @ORM\PreUpdate.

There are some other events you can interact with, so be sure to check out the official docs – they become much more useful now that you understand how they work.

An exception has been thrown during the rendering of a template (“You have requested a non-existent service “http”

Nick-Hewer-Countdown-007I have been running v2.1.10-dev since very shortly after it was released – as I run composer update nightly.

However, I keep finding this error:


An exception has been thrown during the rendering of a template (“You have requested a non-existent service “http” *cut*

After doing an assetic:dump.

As soon as I do an assetic:dump, then a php app/console -V, my version changes from 2.1.10-dev to 2.1.4-dev.

The error above is then thrown when opening a template that uses a render(route) call inside my twig template.

It’s not major, in that running composer update resolves the issue.

For reference, I have deleted the app/cache dir with rm -rf *, as well as cache:clear. I have done this multiple times.

I have decided to remove the entire Symfony folder from vendors (sudo rm -rf vendors/symfony/*) and re-run the composer update.

Hopefully this will clear the issue.

Note: I have resolved the issue raised on the Official Symfony Blog, so if you are seeing this after updating, have Googled and found this page, then you probably haven’t corrected the issue raised on the blog article. Specifically point 6, but make sure to read it all.

And if anyone has got the same issue as I have, please let me know how you resolved it.

If I haven’t updated this post in 7 days, you can take my solution (deleting the Symfony folder from vendors) as working.

Otherwise, I am sure to be back here having a rant.

Ps, yes I am aware the post picture is irrelevant.

How to fix Method Not Found In Class orange warning in PHPStorm

little-miss-helpfulGrrr, how annoying.

My screen is full of orange, but I know these methods are valid.

Your project may be vast in scope, you may have a looming deadline for 5pm tonight, or you may just be a perfectionist who hates the thought of your IDE thinking you are making mistakes.

A good example of this is when using a foreach loop.

You have something like:

foreach( $myEntity as $entity ) {
  $entity->myValidMethod();
}

And PHPStorm says, erm, you make big mistake sir!

Now you have a valid bit of code that’s flagged up in orange as Method ‘myValidMethod’ not found in class My\Name\Space\Path\MyEntity.

Boo, hiss, and such.

It’s simple to fix though – even though it’s taken me over 100 words to get here.

Just add a comment, as such:

/* @var $entity \My\Name\Space\Path\MyEntity */
foreach( $myEntity as $entity ) {
  $entity->myValidMethod();
}

Super.

Now you no longer have a false positive.

Time to get back to meeting your deadline.

How to fix Twig Whitescreen on {{dump(var)}}

This one has been doing my head in for a while now.

Once your forms get past a certain size / complexity, the {{dump(var)}} command tends to bomb out, and throw up a rather unhelpful white screen.

Many of the results on Google tend to say – increase your PHP memory limit – never has more of an impact than taking longer to display the damn white screen.

Boo hiss, shake your first at things, etc.

Anyway, I finally found a solution.

Get your project back on track with the Ladybug Bundle.

{{ ladybug_dump(form) }}

A little of the above gives you a little of the below.

And yes, each section is expandable to give you loads of helpful detail.

example-twig-dump-ladybug-bundle

Excuse the crappy screengrab – I had to resize to get it to fit and it looks gashbag. Hey, I never said I was a designer.

Just a kick ass Symfony 2 expert 😉

Adding new objects to a form field collection

homer-dohI couldn’t think of a good title for this post. So, erm, sorry about that.

Still, if you are reading on, this may save you a headache in the future.

I came across an issue today where I was basically doing this (adding a new option at run time to a form), and it worked.

Kind of.

It would always add in the first option.

And it would add in the second option too, should I add one.

But any above the second were always lost. I couldn’t figure out why the submitted array only ever contained, at most, two items.

Out of sheer luck, I also had another collection sub form inside the very same form, which I had basically copy/pasted from.

Now, this made the whole – why the *expletive deleted* isn’t this thing working?

Turns out, I had set my prototype_name in my Form Type to something different to that in the .text().replace(regex) in my javascript.

Doh.

Still – at least I know for the future. And hopefully, if you ever make a similar mistake, you will now know how to rectify it quickly.

Have you ever used Composer?

logo-composer-transparentYou have, right?

Like all the time. Ever since you found a framework no doubt. I mean, ever since I found Symfony 2, I have used and loved Composer.

Stuff like this amazes me. That the open source community can provide such an incredible feature just for the love of creating helpful software just blows my mind.

But I digress.

If you do use Composer (we already established that you do, right?), then no doubt you have heard of Packagist. Another amazing site / tool / play on words.

packagist-logo

Just this evening I needed it for finding a suitable payment processing class.

Now, it comes back with tons of results. That’s always a great start.

But critically – it doesn’t let you sort the results. Boo. Hiss.

And also, I wanted to send them / him / her a quick bit of feedback, but they (him/her?) want to open my default email client to do so. It’s 2013, get a contact form!

But aside from those two little niggles, it’s such an amazing site. And it helped me find a great payment processing bundle.

Amazing enough to make me write a blog post about it. So it must be doing something right.

Testing Symfony 2 Forms with Multiple Checkboxes

checkbox-gridThe thing I find most frustrating about Symfony’s documentation is that it always seems to fall just shy of getting me over the finish line.

And those extra few yards can take an absolute age to travel.

I needed to test a checkbox field – not the actual ‘checkbox‘ field type, rather an entity field type inside a collection that was rendered with checkboxes (multiple => true, expanded => true).

Three cheers for making that one confusing.

There’s a nice piece inside the dom crawler documentation that kinda explains how to do this, but not exactly:

// check or uncheck a checkbox
$form['registration[terms]']->tick();
$form['registration[terms]']->untick();

Great.

Well, great that is until you realise your form looks more like this:

// check or uncheck a checkbox
myForm[q16][innerQuestionOptions][]

That is – you have maybe 5 checkboxes and they all have that exact same html form field name, but a slightly different ID.

So I tried the ID. No dice.

Then I tried to use the $form->setValue method described in the documentation. Turns out that method is not allowed – not sure why that’s still on there.

Then I found a poor soul who had been through the same trauma I just experienced, over at that wealth of obscure knowledge, Stack Overflow.

Craig, being the good man that he is, not only posted up the problem, but replied – the only reply I might add – with the solution.

It’s people like Craig who make the Internet a better place.

Anyway, for those of you who can’t be arsed clicked all these links I have so helpfully provided, the solution is as follows:

// check or uncheck a checkbox
myForm[q16][innerQuestionOptions][0]->tick();
myForm[q16][innerQuestionOptions][2]->tick();
myForm[q16][innerQuestionOptions][4]->tick();

Where the number is the zero index of the array of buttons you are trying to click.

After that it works like a PyCharm.

Where did all my disk space go?

can-of-wormsI hit a snag this week on my dev box.

The snag being, I was using 100% of the space on my VM.

How? How could this be? I had a single Symfony site, a database, and neither were that big.

But development had been going on a while, and I had noticed on ssh’ing in, that Ubuntu was telling me that my disk space was slowly but surely diminishing.

Silly me for only setting up an 8gb VM.

But still, a little strange.

Anyway, I did the usual – php app/console cache:clear – which got me some space back, but not much.

I added a new disk in VMWare and followed the GParted Live CD instructions, but then it turns out that won’t work for VMWare. You have to extend the LVM (or something!) and frankly, I didn’t have time nor the inclination to do any of that.

Still, the cache:clear had got me a little bit of breathing room. Enough to allow me to work through yesterday.

Then today, I was dropping and recreating the schema, and lo-and-behold, the disk ran out of space again.

Frustrating.

me@my-ubuntu:/var/www/html/mySite$ df
Filesystem                   1K-blocks    Used Available Use% Mounted on
/dev/mapper/ubuntu--tlf-root   6946528 6593648        12 100% /
udev                            505076       4    505072   1% /dev
tmpfs                           205056     292    204764   1% /run
none                              5120       0      5120   0% /run/lock
none                            512636       0    512636   0% /run/shm
/dev/sda1                       233191  139705     81045  64% /boot

🙁

Then I figured, well, why not manually kill the entire cache directory and see where that gets me:

me@my-ubuntu:/var/www/html/mySite/app/cache$ sudo rm -rf *
me@my-ubuntu:/var/www/html/mySite/app/cache$ df
Filesystem                   1K-blocks    Used Available Use% Mounted on
/dev/mapper/ubuntu--tlf-root   6946528 5081080   1512580  78% /
udev                            505076       4    505072   1% /dev
tmpfs                           205056     292    204764   1% /run
none                              5120       0      5120   0% /run/lock
none                            512636       0    512636   0% /run/shm
/dev/sda1                       233191  139705     81045  64% /boot

Let’s just say the machine made some seriously grunty sounds, but it did the job.

Still, I think next time I will go for a 16gb drive just to be sure.