Artisan Développeur

Qualité, amélioration continue, agilité, professionnalisme.

Results for tag "symfony"

3 Articles

Mochajs locally in your symfony project

How to install node and mocha locally to unit test you javascript code

I will install packages in the require-dev section of my composer.json file, because in this case, I only use nodejs and mocha in the dev, preprod and test environments and they use the requierdev.
I don’t want to install that on my production environment.

To do that, I use two composer packages:

mouf/nodejs-installer

Packagist: https://packagist.org/packages/mouf/nodejs-installer
Github: https://github.com/thecodingmachine/nodejs-installer

koala-framework/composer-extra-assets

Packagist: https://packagist.org/packages/koala-framework/composer-extra-assets
Github: https://github.com/koala-framework/composer-extra-assets

Here the installation

You have to add this to composer.json file:

"require": {
    "mouf/nodejs-installer": "^1.0",
    "koala-framework/composer-extra-assets": "~1.1"
},
"extra": {
    "require-dev-npm": {
        "mocha": "*"
    }
}

To use mocha locally you have to add one file to the bin directory of your symfony project

In the script section, both in « post_install_cmd » and « post_update_cmd »

"touch bin/mocha && chmod +x bin/mocha && echo '#!/bin/bash \n DIR=$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd ) \n export PATH=$DIR/../vendor/nodejs/nodejs//bin:$PATH \n ../node_modules/.bin/mocha \"$@\"' > bin/mocha"

Example:

],
    "scripts": {
        "post-root-package-install": [
            "SymfonyStandard\\Composer::hookRootPackageInstall"
        ],
        "post-install-cmd": [
            [...] //do not copy/paste, it's just an example !
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles",
            "touch bin/mocha && chmod +x bin/mocha && echo '#!/bin/bash \n DIR=$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd ) \n export PATH=$DIR/../vendor/nodejs/nodejs//bin:$PATH \n ../node_modules/.bin/mocha \"$@\"' > bin/mocha"
        ],
        "post-update-cmd": [
            [...]  //do not copy/paste, it's just an example !
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles",
            "touch bin/mocha && chmod +x bin/mocha && echo '#!/bin/bash \n DIR=$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd ) \n export PATH=$DIR/../vendor/nodejs/nodejs//bin:$PATH \n ../node_modules/.bin/mocha \"$@\"' > bin/mocha"
        ]
    },

This line will create the mocha file and set the execution permission.

To actually install these:

composer install

Create a js directory src/Tests

With you IDE, or

mkdir src/Tests/Js

Finally use it just like that

Run all tests files:

bin/mocha src/Tests/Js/*

Or specific one:

bin/mocha src/Tests/Js/file.js

That’s it ! You can now unit test easily your javascript code !

As always, if you have question,  better practice, suggestion comment !

Don’t miss 500 internal error anymore with symfony and monolog

Sometimes I read my server logs … Like some people read the newspaper, in fact server logs are like the app newspaper 🙂

Every morning I am reading my logwatch email.

But I can miss errors, and even if I see them, it is the next day in my logs email, and it is really BAD

The solution is simple, use monolog to send you errors directly

https://symfony.com/doc/current/logging/monolog_email.html

My configuration is (config_prod.yml):

monolog:
    handlers:
        main:
            type:   stream
            path:   "%kernel.logs_dir%/%kernel.environment%.log"
            level:  error
        mail:
            type:         fingers_crossed
            # 500 errors are logged at the critical level
            action_level: critical
             handler:      deduplicated
        deduplicated:
            type:    deduplication
            handler: swift
        swift:
            type:       swift_mailer
            from_email: 'email@myserv.myserv'
            to_email:   'mymorningemail@myserv.myserv'
            subject:    'You have to work ! An Error Occurred! %%message%%'
            level:      debug
            formatter:  monolog.formatter.html
            content_type: text/html

 

 

Symfony error: 500 Internal Server Error – SyntaxErrorException

This article is at first a reminder for me, and if it can helps someone it’s even better 😉

When you work with a ORM (Doctrine for me, with Symfony) you have to think data as entities, objects instead of  database tables.

You are moving away from database (mariaDB in my case) and his constraints, it is a good thing for severals points, but there is one you can forget about and time to time you fall into his trap, and you get a really pretty error message.

An exception occurred while executing ‘INSERT INTO my_table (createdAt, updatedAt, name, commercialName, VAT,  oneField, anotherField, foo, bar, again, andAgain, default) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)’ with params [« 2018-02-23 13:55:24 », « 2018-02-23 13:55:24 », « my company », « really nice company », « 20 », null, « 1 », « 0 », null, null, null, null, 0]:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘default) VALUES (‘2018-02-23′ at line 1’
500 Internal Server Error – SyntaxErrorException
2 linked Exceptions:

PDOException

No more suspense here, the trap is quite simple and very basic, it’s the reserved keywords.

Reserved Keywords needs to be managed correctly if you want to use them, below see a real life example:

I need to know if a company is the default one for my user, I add a property name « default » (I use annotations for the doctrine mapping) and bam, SQL is broken.

    /**
     * @ORM\Column(type="boolean", nullable=false)
     */
    private $default = false;
doctrine field

The above  error message is pretty clear when you think about the keywords, because Doctrine use the property name to create the database field, the new field is:

`default` tinyint(1) NOT NULL

And when you want to insert a company:

INSERT INTO my_table (createdAt, updatedAt, [...], default ) 

« default » is not quoted, and mariaDb rise an error.

Fortunately we have several solutions, and my personal (subjective) choice:

Rename your property to something not reserved like « defaultCompany »

$company->isDefaultCompany();

I don’t like that, because the entity is a Company, if you name your variable $company to store it, it is not nice to read.

Quote the field name (in the annotations – doc here)

    /**
     * @ORM\Column(name="`default`", type="boolean", nullable=false)
     */
    private $default = false;

I don’t like this one either, it is better than the first but it can lead to complications (see the linked documentation)

Force a field name with the annotations

    /**
     * @ORM\Column(name="defaultCompany", type="boolean", nullable=false)
     */
    private $default = false;

Since we need to add the name of the database field if we want to quote it, I prefer have a non reserved keyword, unquoted, and never be worried by some obscure bug or malfunction because I want so bad to use this field name.

With Doctrine you are almost never in the database, it is not a big deal to have a « defaultCompany » field in the « company » table.

It is bother me when I read my code, but I don’t spend time in the SQL, I prefer have this little ugliness in my DB than in my code.