Tuesday, October 22, 2019

Symfony file upload mysterious error

Uncaught PHP Exception Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException: "The file "" does not exist" at /var/app/current/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php line 116 {"exception":"[object] (Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException(code: 0): The file \"\" does not exist at /var/app/current/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php:116)"}


If you see this error the odds are high that you are trying to upload a file larger than the max values set in you php.ini config file (upload_max_filesize and post_max_size).

Wednesday, October 2, 2019

Symfony service container: binding arguments by name or type

This cool feature was introduced in Symfony 3.4 (https://symfony.com/blog/new-in-symfony-3-4-local-service-binding) but I didn't use till today.

Example: create a custom Monolog channel and inject the service in controller (Symfony 4).
I was thinking that I will have to create some sort of custom service definition in order to inject the service "monolog.logger.mychannel" into my controller, but no, it was way easier.

In services.yaml  just add:



services:
    # default configuration for services in *this* file
    _defaults:
        bind:
            # pass this service to any $mychannelLogger argument for any
            # service that's defined in this file
            $mychannelLogger: '@monolog.logger.mychannel'

Now is super easy to inject the service in controllers by adding "$mychannelLogger" in the list of function parameters:


/**
     * @Route("/{id}", name="project_update", methods={"POST"})
     */
    public function delete(Request $request, LoggerInterface $mychannelLogger): Response
    {
    


Read more about it in Symfony docs: https://symfony.com/doc/current/service_container.html#services-binding


Wednesday, September 18, 2019

Custom user provider using multiple database connections with Doctrine and Symfony 4

Situation :

I am using Symfony 4.3 and autowiring.

I have 2 Doctrine database connections, a default and "users" connection:



doctrine:
    dbal:
        default_connection: default
        connections:

           .....
    orm:
        auto_generate_proxy_classes: true
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Main'
                        prefix: 'App\Entity\Main'
                        alias: Main
            users:
                connection: users
                mappings:
                    Users:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/UsersManagement'
                        prefix: 'App\Entity\UsersManagement'
                        alias: Users

So my User entity was managed by the secondary connection "users". Checking from command line would show me that everything is mapped correctly:

php bin/console doctrine:mapping:info --em=users

 Found 7 mapped entities:

 [OK]   App\Entity\UsersManagement\User

Also when loading users I am using a customer query by making UserRepository implement the UserLoaderInterface. (https://symfony.com/doc/current/security/user_provider.html).

security:
    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        app_user_provider:
            entity:
                class: App\Entity\UsersManagement\User

But when I try to login, ugly surprise this error pops:
 "The class 'App\Entity\UsersManagement\User' was not found in the chain configured namespaces App\Entity\Main" 

 After googling a little bit I get to this life saving comment from stof: https://github.com/symfony/symfony/pull/8187#issuecomment-18910167


Here is how you configure it:

security:
    providers:
        my_provider:
            entity:
                class: Acme\DemoBundle\Entity\User
                manager_name: users  #non default entity manager

So there is a 'secret' parameter "manager_name" that you need to add to security.yml and is not enough that the entity is correctly mapped by Doctrine.

If somebody ever finds this useful please add a comment :D