Updated with EasyCodingStandard 5, Neon to YAML migration and checkers
to services
migration.
Do you know *.neon
format? It's config file format created in Czech Republic by David Grudl (author of Nette) and if you're foreigner, you might know it from or EasyCodingStandard and PHPStan. Even suggested as composer.neon
.
And *.yaml
is similar format used almost everywhere else.
You spot the suffix is different, but what about syntax differences? And which one is better?
None of them is perfect, they both have strong parts and weak parts. But the more I travel to abroad conferences, meetups or repositories, the more I hear nobody understand differences between them or their advantages to each other. Since I meet mainly with Symfony and Nette code, I had to investigate them a bit deeper.
There are no solutions. There are only trade-offs.
Here is a summary of what I found and how to migrate to each other. I'll write about differences and places, where syntax fail me the most.
70 % of syntax is similar:
services:
Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer: ~
But what about?
items:
-
- { key: value }
Of course you can Google documentation and try to understand it. But documentation is incomplete or for older version than you use. The best way to learn it for me is with online parsers:
Neon
As neon was born as free format, it allows to use both spaces and tabs.
Yaml
Only spaces are allowed. Since most of projects have coding standards, I prefer using one format in whole code.
services:
- SomeService
SomeService: ~
Neon
Could you guess the output? 1 item? Syntax error?
array (1)
services => array (2)
0 => "SomeService" (11)
SomeService => "~"
Neon allows to combine indexed arrays and lists. And do you work with or create with such lists in PHP?
Yaml
Parsing would fail there, because Yaml allows only one approach:
services:
- SomeService
- SomeService
# with 2 items in array
or
services:
SomeService: ~
SomeService: ~
# with 1 item
This difference is one of the biggest WTFs, because I had to think about format and possible merge error every time I used lists... or indexed arrays... or is it arrays? Uff.
I write posts in Statie, where you can use Yaml to configure per-post variables like perex:
Neon
perex: '''
This is long multiline perex,
that takes too much space.
'''
Note it can be aligned to left side.
Yaml
perex: |
This is long multiline perex,
that takes too much space.
But here it must be indented on every line.
Neon
In Neon you can use entities and do this:
someValue: Column(type=int, nulls=true)
Could you guess what it is? Parameters, arguments, service decoration?
array (1)
someValue => Nette\Neon\Entity
value => "Column" (6)
attributes => array (2)
type => "int" (3)
nulls => true
Personally I prefer explicit, clear naming combined with easier scalability:
someValue:
value: "Column"
attributes:
type: "int"
nulls: true
Yaml
You can do similar shenaniganz with Yaml as well thanks to Symfony\ExpressionLanguage
services:
App\Mailer:
arguments: ["@=service('App\\\\Mail\\\\MailerConfiguration').getMailerMethod()"]
If you want to see real-life example, I tried it once. But went quickly back because I could not remember what exactly that means and how it work.
This is the most important question when it comes to open-source code. You can create your own natural language, that is smart, easy to learn, context aware and super fast. But what if 1.39 billion people speaks English already?
Neon
You can install Neon Plugin, that handles param and class autocomplete very nicely. It's enabled for every *.neon
file by default.
Yaml
Yaml support is included in Symfony Plugin. It needs to by enabled per project. It works great, there is just one last thing I miss. It already completes services for Symfony 3.2- format:
services:
some_name:
class: AutocompletedClass
But since Symfony 3.3 there is short syntax for services:
services:
ManuallyTypedService: ~
And it is missing autocomplete in time being. Do you want autocomplete for this case too? Upvote this issue or send PR in Java to the plugin.
Also Github lacks of Neon support.
Which one to pick? It depends on what is important to you. If you use Nette and work in Czech company and Neon is weapon of choice for you - it's ok.
But what if you're making open source for the whole world?
I was on a train trip in Hungary and I was thirsty. I went to classic food shop and pick first bottle with still water I saw. I wanted still water cause gas hurts me and wanted to drink a lot. And I'm drunk when it comes to water in summer.
At least I though I picked the right one until I opened it. In every single country I've been to so far, the blue is always still water. But not in Hungary!
As Chris says: "In Hungary the color code is reversed where blue means sparkling and red means flat." And there is even question on Tripadvisor on this topic.
For all the reasons above (thirsty-human-friendly-bottle-colors included), after looking at problem from various points of view and discussing with my Github and PHP friends, I came to conclusion that Yaml is better for me.
But EasyCodingStandard was running on Neon that was loaded by my few classes to Symfony Kernel, so how to migrate to Yaml?
Imports
-includes:
+imports:
- - packages/EasyCodingStandard/config/psr2.neon
+ - { resource: 'packages/EasyCodingStandard/config/psr2.yml' }
- - common/array.neon
- - common/control-structures.neon
- - common/docblock.neon
+ - { resource: 'common/*.yml' }
Lists
services:
# class should be Abstract or Final
- - SlamCsFixer\FinalInternalClassFixer
+ SlamCsFixer\FinalInternalClassFixer: ~
ArrayFixer: ~
Quoting parameters
parameters:
skip:
SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff:
- - *packages/CodingStandard/src/Sniffs/*/*Sniff.php
+ - '*packages/CodingStandard/src/Sniffs/*/*Sniff.php'
Multi-lines
-perex: '''
+perex: |
Do you know `*.neon` format? It's config file
-format created in Czech Republic...
+ format created in Czech Republic...
-'''
And from *.yml
to *.neon
? Just revert -
and +
:).
To see what code exactly had to change:
Which format do you prefer and why? Do you have some other WTF examples or migration tips? Let me know in the comments!
Happy coding!
Do you learn from my contents or use open-source packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!