PHPUnit: contains vs. stringContains

Note to myself: If I ever see that error again when running PHPUnit tests

Invalid argument supplied for foreach()

phar://C:/Program Files (x86)/PHPUnit/phpunit.phar/PHPUnit/Framework/Constraint/TraversableContains.php:110
phar://C:/Program Files (x86)/PHPUnit/phpunit.phar/PHPUnit/Framework/Constraint.php:82
phar://C:/Program Files (x86)/PHPUnit/phpunit.phar/PHPUnit/Framework/Constraint/And.php:113

please remember that $this->contains() is not the same as $this->stringContains(). The first one is a constraint for arrays, the second one is for strings.

SonataNotificationBundle does not consume messages

Today I was playing around with SonataNotificationBundle. I simply followed the installation instructions, but I encountered some problems.

First problem: You have to manually add SonataEasyExtendsBundle as a dependency. For some reason it is not automatically added by Composer. I guess they’ve just forgot it in the composer.json, so maybe this problem is already fixed by the time you read this.

After the bundle was working I’ve implemented a new component to dispatch some messages. Everything was working fine, I could even see the message in the database (used Doctrine for the message queue). To complete that test scenario I implemented a consumer for my message type and registered it as a tagged service. I started the consumer job as described in the documentation …

app/console sonata:notification:start --env=prod --iteration=250

… but nothing happend!

Second problem: The messages did not process. Some debugging in the code showed me that it only fetched messages with type default from the database. This was strange, because the console told me that my message consumer is registered and there was no default type at all. I did some research on this problem and found a very useful post of someone having the exact same problem. There was as a working configuration in the thread so a gave it a try – and it worked! The trick was to configure at least one queue. Your configuration should look similar to this:

sonata_notification:
    queues:
        - { queue: catchall, default: true }

The catchall is just a name for the queue, it can be anything. It’s more important to make it the default queue, which is done with default: true.

Loading assets from a different server

In a production environment you’ll eventually want to load assets (images, CSS and JS) from a different server. Perhaps you’re running your own asset server or you’re even using a CDN. This will require the files to be linked with an absolute URL. But in your development environment you don’t want this – you want assets to be loaded directly from the same server.

So this is what you do. Use Symfony’s asset() function for every asset you want to load from the asset server:




If you’re using Assetic you’ll have to add the asset() function to asset_url:

{% javascripts '@AcmeFooBundle/Resources/public/js/*' %}
    
{% endjavascripts %}

Now you can have different configuration for your production and development environment:

framework:
  templating:
    engines: ['twig']
    assets_base_urls: http://assets.yourdomain.com
framework:
  templating:
    assets_base_urls: ~ # Files are loaded with relative path

Some hints when Assetic is not compiling

We’re sometimes having the problem that Assetic is not compiling for some reason. It tries to compile files, which are actually not referenced anywhere in the project. This especially happens when switching branches while an Assetic dump is running in the background (with watch option enabled).

Here are the steps we usually do to get the problem fixed:

1) Restart Assetic dumper
Ok, that one is obvious. Restart the Assetic dumper to refresh its information. Just like a reboot of Windows 😉

2) Clear cache
Sometimes there is wrong information in the cache directory of the dev environment. Delete the whole app/cache/dev directory to get a clean new build. Then restart the Assetic dumper.

3) Take a look at the temp directory
Assetic writes some files to the temporary directory of your operating system. Search for files named assetic_* .  and delete them. Then restart the Assetic dumper.

Hope this helps!

Decorating Blocks in Twig

This is a simple trick how you can dynamically decorate a block in Twig.

Let’s say your design has a fanzy sidebar but you only want to display it when it has some content. In Twig you would usually solve this creating two seperate base templates. One, which includes a block named “sidebar”, and another one without it. This is quite easy, but then you’ll have to make sure you’re using the right base template. In addition you’ll have to maintain two base templates, even if they’re identical except for the sidebar.

So is there something else we could do, to make life more easy? Sure, we could put some more logic into to base template: Let’s check if the sidebar block has content! In that case we will display the content of the block embedded in some extra HTML.

This is how a base.html.twig might look like:

{% set sidebarContent = block("sidebar") %}
{% if sidebarContent %}
	
{% endif %}

First we’re fetching the content of the block into a variable with Twig’s block function.  Now we can check if there’s some content in it, so we can display the HTML container and the sidebar content on demand. Note that you have to use the raw filter on the block content since it is already sanitized HTML.

Welcome to the Blog

Hello everybody!

My name is Christian, I’m a developer from Berlin/Germany. Primarly I’m programming in PHP but I’m open to any kind of programming language or web technology as long as it can do the job. When creating PHP applications I prefer using the Symfony2 framework, which is why most of my blog will be related to it and the so called “Symfony ecosystem”.

This blog will be about my experience with new technologies and the lessons learned, so people like you can benefit from it. I guess it will be updated on a non-regular basis, that means it just happens when I’ve found a new technology or had a experience worth sharing. I already got some topics scheduled but I have to write them first 😉