Stream an image from Symfony controller

When sending an image/file from a Symfony controller you would usually read the file from filesystem.
This you can do by passing the file path to the BinaryFileResponse class and return it in the controller, as described in the docs:
https://symfony.com/doc/current/components/http_foundation.html#serving-files

use Symfony\Component\HttpFoundation\BinaryFileResponse;

$file = 'path/to/file.txt';
$response = new BinaryFileResponse($file);Code language: PHP (php)

But in some cases you might want to create an image dynamically and return it directly from the controller without storing it on the filesystem.
So you can create your image with the GD library and directly stream the GDImage object from the symfony controller with the StreamedResponse class.

Continue reading “Stream an image from Symfony controller”

Doctrine migrations and Postgis

Using Postgres with the Postgis extension to integrate GeoData / GIS functionality in your project is not natively supported by Doctrine and Doctrine migrations.

First you have to add the extension to Postgres, even if you use the Postgis docker image like postgis/postgis:14-3.3-alpine.

So add this SQL statement to the up method of your first migration:
$this->addSql('CREATE EXTENSION IF NOT EXISTS postgis;');

and the DROP statement for the extension to the down method:
$this->addSql('DROP EXTENSION postgis;');

Now, when using Doctrine with Postgres and Postgis extension, migrations still behave a bit odd and try to remove Sequences created by Postgis, because Doctrine migrations does not take Postgis extension’ s built-in Sequences into account.

Continue reading “Doctrine migrations and Postgis”

Symfony deprecation log channel

Are you annoyed of too many deprecation warnings in you logs of your symfony app?
Probably yes because it is really a lot of noise.
However deprecation logs are still useful to ensure future compatibility of your app.

So since version 5.1 symfony will log deprecations to a dedicated log channel when it exists and ships with this monolog config:

monolog:
    channels:
        - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it existsCode language: PHP (php)

This is added already in the recipe and ships when installing symfony.

Ok, but the handler for this deprecation channel is not configured, so you have to do this yourself.
How? Add this to your monolog config:

Continue reading “Symfony deprecation log channel”

Converting umlaute with symfony String component

There are multiple PHP native ways to convert umlaute and other special characters to ascii save formats, but most of them i experience insufficient in the one or other way.

Since i am using symfony anyway i can use the String component which has a handy slugger which converts any characters into safe ascii characters.
It is very flexible and can be customized with locales, custom replacements and closures.

$umlautString = "Müller Meier";
$slugger = new Symfony\Component\String\Slugger\AsciiSlugger('de');
$slugger->slug($umlautString, $seperator = ' ')->toString();
echo $umlautString; // mueller meierCode language: PHP (php)

I guess this will become my go-to method resp. slugger to convert umlaute in any PHP application.

Continue reading “Converting umlaute with symfony String component”

Class “Psr\Log\Test\TestLogger” not found

The psr/log package used to have not only the Interface for PSR-3 Logger, but also actual implementations of the interface like the TestLogger.
The TestLogger could be used as mock for any PSR-3 Logger in your test cases.

However from v3 the TestLogger was removed, so that the psr/log package would focus solely on the Interface.

If you used the TestLogger in your project and you or some of your dependencies upgraded psr/log to >= v3 you most likely saw this error:

Class "Psr\Log\Test\TestLogger" not found

Continue reading “Class “Psr\Log\Test\TestLogger” not found”

Migrating user table from Mysql to Postgres with Symfony and Doctrine

When using bin/console make:entity on Mysql and then later you switch your application to Postgres and you have a table called user, which you most likely have when using security component of Symfony.
Then you will receive an error because user is a reserved word in Postgres!

An exception occurred while executing 'INSERT INTO user (id, email, roles, password, is_verified) VALUES (?, ?, ?, ?, ?)' with params [3, "dev@dev.de", "[]", "your-encrypted-password", 0]:
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "user"
LINE 1: INSERT INTO user (id, email, roles, password, is_verified) V...

Continue reading “Migrating user table from Mysql to Postgres with Symfony and Doctrine”

Passing a boolean to the constructor of “Symfony\Component\Dotenv\Dotenv” is deprecated

You might encounter this deprecation message after your upgrade to symfony 5.1 in your symfony project:

Since symfony/dotenv 5.1: Passing a boolean to the constructor of “Symfony\Component\Dotenv\Dotenv” is deprecated, use “Dotenv::usePutenv()

To fix this, go to config/bootstrap.php and remove the false from the Dotenv constructor:
(new Dotenv(false))->loadEnv(dirname(DIR).'/.env');
to
(new Dotenv())->loadEnv(dirname(DIR).'/.env');
See: https://github.com/symfony/symfony/issues/37195

Actually the file config/bootstrap.php has been removed from symfony 5.1 and was replaced in public/index.php.

But since the project was updated from an symfony 4 version the bootrap file is still present.

So another option would be to remove the boostrap file and update the project entirely to symfony 5.1 recipe.
This is not trivial though as you can see in this corresponfing PullRequest.

EU/VAT – Mehrwertsteuer Madness

Calculating European VAT Rates with PHP – the easy way.

Disclaimer: No legal advice, just a little experience report.

If you sell digital things (services, digital goods etc.) to EU countries, you might have to calculate the VAT at the rate of the customer’s country (and even pay it there afterwards).
The latter is even the more inconvenient part, but at least the first part can be done quite easily with good old PHP.

Continue reading “EU/VAT – Mehrwertsteuer Madness”

Psalm Static Analyzer fails with Symfony’s builtin preloading file

So i updated a symfony app the other day to version 5.1.6 and suddenly the static code analyzer psalm ran appearently in an hangup loop and never terminated.

After some investigation it showed that symfony added a .preload.php file to the src directory to enable the new PHP7.4 preloading feature.

Unfortunatly psalm parsed this file and followed all includes.
This took it so long that i took it for an endless loop.

There is some discussion in symfony github issues about this and the conclusion was to replace src/.preload.php with config/preload.php which happens now in a recipe.

Continue reading “Psalm Static Analyzer fails with Symfony’s builtin preloading file”