Door Sander den Heijer

Product Lead

Upgrade naar Symfony 4 - Development-iteratie #154

23-04-2019 • 14:25

33

Onze developers hebben iteratie #154 opgeleverd. De grootste wijziging is deze keer het live gaan van de upgrade naar Symfony 4.

Upgrade naar Symfony 4

Symfony 4 werd al in mei 2017 aangekondigd en werd uiteindelijk in november 2017 vrijgegeven. Het was echter ook meteen duidelijk dat het, net als bij Symfony 3, een flinke kluif zou worden om te upgraden. Aangezien de door ons gebruikte lts- (long-term support-) versie 3.4 nog tot eind 2020 wordt ondersteund, hebben we deze upgrade als een van onze technische projecten op 'de lijst' gezet. Op die manier konden we die upgrade ook de aandacht geven die nodig is.

Drie sprints geleden was dit Symfony 4-project aan de beurt. Daarbij hebben we gelijk de nieuwste stabiele versie (4.2.7) genomen. Bovendien hebben we ons best gedaan om nieuwe deprecations op te lossen, zodat we makkelijk(er) naar 5.0 zouden moeten kunnen. In de praktijk blijkt echter steeds weer dat zo'n upgrade een flinke opgave is en dat deprecations oplossen meestal slechts de eerste stap is van een lange lijst taken. Deze upgrade bevatte uiteindelijk meer dan veertig commits waarin bijna duizend bestanden werden verplaatst, verwijderd of veranderd.

Aanpak

Zoals veel softwarelibraries bereidt Symfony je voor op upgrades door onderdelen die in een latere versie worden verwijderd, alvast als deprecated aan te merken. Na het oplossen van de deprecationmeldingen uit 3.4 konden we daadwerkelijk beginnen aan de upgrade naar Symfony 4.

We hebben ervoor gekozen om niet alleen de Symfony-versie in composer.json te veranderen in 4.2.*, maar om een nieuw, kaal Symfony-project te maken en daar al onze code naartoe te kopiëren. Toen alles daarin werkte, hebben we alles behalve de .git-directory in het normale project verwijderd en dit nieuwe project daarvoor in de plaats gezet. Hierdoor hadden we de minste kans om vast te lopen met conflicterende code tussen Symfony 3 en 4, en was de kans kleiner om iets te vergeten, achter te laten of fout te doen.

Bundles

Een van de grootste wijzigingen waar we tegenop zagen, bleek uiteindelijk gelukkig niet direct nodig te zijn. Eigen bundles werden als verleden tijd beschreven, maar konden, in ieder geval bij ons, in werkelijkheid gewoon gebruikt blijven worden. Onze bundles zijn voor ons vooral handige plekken om controllers, routes en templates te groeperen. En daardoor werkten ze ook goed samen met Symfony 4. Dat groeperen kan echter ook met praktisch gebruik van directories en namespaces. Daarom zijn we nadat de upgrade naar Symfony 4 was afgerond, doorgegaan om ook onze paar bundles met elkaar te integreren.

Nieuwe deprecations

Ondanks het oplossen van de deprecationmeldingen uit 3.4, kregen we bij het testen weer allerlei nieuwe deprecationmeldingen doordat Symfony met 4.1 en 4.2 nieuwe code zo heeft gemarkeerd. Deze meldingen vervuilden de console-output en -logging, waarop we hebben besloten om die ook gelijk op te lossen. Dit waren onder andere deprecations met betrekking tot routebeschrijvingen en translations.

Oud:
['_controller' => 'TweakersFrontpageBundle:Crew:overview']
Nieuw:
['_controller' => [CrewController::class, 'overviewAction']]

Voorbeeld van een wijziging van de routes, van bundlenotatie naar methodereferentie van de controllermethode.

Voor de routes was het vooral een uitgebreide find-replace. Met in totaal iets meer dan zeshonderd routes hebben we dat overigens niet allemaal handmatig gedaan. Uiteindelijk bleek de log-output van Symfony goed te gebruiken om die in een php-scriptje in te lezen en met wat regular expressions de routes allemaal automatisch te vervangen ;)

Translations

Bij de translations was dat minder eenvoudig. Dat komt vooral doordat Symfony weliswaar aankondigde dat er een nieuwe manier van werken is, maar niet uitlegde hoe dat nou echt werkt. Het is op zich heel mooi dat ze nu een volgens ICU gestandaardiseerde manier van translations hanteren, maar het bij elkaar rapen van de nodige documentatie over de werking en het uitvogelen van slecht of helemaal niet gedocumenteerde wijzigingen in Symfony heeft ons uiteindelijk enkele dagen gekost.

Gelukkig is de nieuwe vorm van translations ook gelijk wat krachtiger. Zo is het nu mogelijk om niet alleen op basis van aantallen een keuze te maken, plural genaamd, maar ook op basis van tekstuele waarden: select. En het is nu onnodig om dat apart via transchoice te doen, dat is onderdeel van trans geworden.

Oud, twig en translation:
{{ 'number_of_reviews'|transchoice(userReviewCount) }}
number_of_reviews:
  "{0}|{1}1 gebruikersreview|]1,Inf[%count% gebruikersreviews"

Nieuw, twig en translation:
{{ 'number_of_reviews'|trans({'count': userReviewCount}) }}
number_of_reviews:
  "{count, plural, =0 {} 
    one {1 gebruikersreview} 
    other {# gebruikersreviews}}"

Twig-translation voor het tonen van het aantal reviews, waarbij voor 0 reviews geen tekst wordt getoond

Dit is een behoorlijk grote wijziging in de translation, maar dat komt vooral doordat het semantisch anders werkt. Bij transchoice geef je een count mee en daarmee selecteert die functie de juiste translation. En daarin kan dan weer de %count%-tekst worden geïnjecteerd. Bij de nieuwe manier van werken is er een variabele count, die met {} wordt gemarkeerd. En bij die variabele wordt hier aangegeven dat de plural-functionaliteit daarop moet worden toegepast. Daarbij zijn bij de ICU per bekende taal losse regels mogelijk voor meervouden; dat maakt het tamelijk complex als er veel vertalingen moeten worden ondersteund, maar ook erg krachtig. Zo kent het Nederlands slechts 'one' en 'other', heeft India zelfs alleen maar 'other' en heeft het Welsh juist 'zero', 'one', 'two', 'few', 'many' en 'other'.

Bij het veranderen van de translations moet verder nog de bijbehorende translationfile worden voorzien van een nieuwe naam: articles.nl.yml wordt dan articles+intl-icu.nl.yml. Op die manier herkent Symfony dat de nieuwe MessageFormatter gebruikt moet worden.

Op dit moment hebben wij alleen Nederlandse translations. We gebruiken de functionaliteit vooral om, in nieuwe templates, de teksten te ontkoppelen van de html-code. We hebben vooralsnog geen plannen om Tweakers in verschillende talen aan te bieden.

Opvallende zaken

Tijdens dit project zijn ons een paar dingen opgevallen. Daarbij zaten uiteraard ook positieve zaken. Zo lijkt het erop dat Symfony, zoals zelf aangegeven, met de nieuwe versie inderdaad sneller is geworden. We hebben dit helaas nog niet uitgebreid kunnen testen, omdat onze productieomgeving significant anders is en anders wordt belast, maar dat gaan we uiteraard in de komende tijd in de gaten houden.

Met Symfony Flex gebeuren nog wel wat vreemde dingen. Zo worden er soms bij composer install nieuwe bestanden aangemaakt of bestaande aangepast. Terwijl dat alleen bij commando's als composer update of require zou mogen gebeuren. Daarvoor is in de tussentijd in ieder geval één bug gefixt. We gebruiken het nog niet lang genoeg om te kunnen beoordelen of dit vaker gebeurt of alleen tijdens de upgrade van 3.4 naar 4.2. Het ging behalve om symfony.lock om de bundles.php, .gitignore en diverse configuratiebestanden.

Verder bleek dat de upgrade guide op zich wel een nuttige bron van informatie is, maar uiteindelijk ook de nodige gaten bevat. Er staat bijvoorbeeld in dat allerlei files uit de app-directory verplaatst moet worden, maar geen expliciete melding dat die hele directory in Symfony 4 niet meer gebruikt zou moeten worden. En bij de melding dat views uit app naar templates zouden moeten, wordt niet gemeld dat dat alleen voor twig-templates geldt. De php-templates moeten naar src/Resources/views. En als je dat gedaan hebt, word je doodleuk geconfronteerd met een deprecationmelding dat je die directory niet meer zou moeten gebruiken :o

Xdebug

Ongeveer tegelijk met de start van ons Symfony-project hebben we onze testomgevingen voorzien van een upgrade naar PHP 7.3, met ook de nieuwste versie van Xdebug, 2.7.0. Normaal gesproken betekenen dat soort upgrades dat het allemaal wat sneller wordt, maar echt veel merken jullie en wij daar niet van. Dit keer werd php juist veel trager. 'Gelukkig' gold dit ook voor versies van onze site die nog met Symfony 3 werkten, waardoor die upgrade al snel als oorzaak afviel :)

Onze systeembeheerder Kees is daarna op zoek gegaan naar de oorzaak. Het bleek dat dit door de nieuwe Xdebug kwam; ook PHP 7.2 werd met die versie significant trager. Na nog meer onderzoeken met strace bleek dat de oorzaak zat in het feit dat er vele miljoenen aanroepen van de 'getpid' system call werden gedaan. Een paar keer aanroepen is niet zo erg, maar die grote hoeveelheid gaf een 'death by a thousand paper cuts'. Xdebug voerde deze methode uit op de plek waar het steeds opnieuw, bij elke functiecall in de php-code, moest controleren of het was geactiveerd. Het probleem kon uiteindelijk eenvoudig worden opgelost met een verandering van een paar regels code. Ondertussen is versie 2.7.1 van Xdebug uitgekomen, waarin de patch van Kees is meegenomen.

En verder

Best Buy Guides op frontpage

Als onderdeel van de al eerder besproken vernieuwingen tonen we nu op de frontpage een product uit de recentste Best Buy Guide met daarbij relevante links naar de Best Buy Guide en de productpagina in de Pricewatch. Verder vullen we het uitgelichte blok aan met verwijzingen naar de populairste Best Buy Guides van het moment.

Custom CSS

Na de release van de recente wijziging aan de frontpage hebben we behoorlijk wat feedback gehad. Daaruit blijkt dat een deel van jullie bij het bekijken van de frontpage vooral behoefte heeft aan een direct zichtbare, compacte listing en minder aan de zaken eromheen. Dat is via custom CSS redelijk eenvoudig te realiseren, maar we snappen dat niet iedereen daarover beschikt. Om jullie hierin tegemoet te komen, hebben we de hoeveelheid karma die nodig is om custom CSS te kunnen gebruiken, flink verlaagd.

Tot nog toe was dit alleen beschikbaar voor hero- en elite-abonnees en via de karmastore voor actieve tweakers die minimaal 500 karmapunten per half jaar haalden. Dat laatste is veranderd. Nu is custom CSS in de karmastore beschikbaar voor iedereen die minimaal 4096 karma in totaal heeft bereikt. En het blijft daarna ook actief. Het is daardoor voor een grotere groep tweakers beschikbaar en je hoeft ook niet meer actief te blijven na het eenmalig te hebben geactiveerd.

We hebben een aantal ideeën om het uitwisselen van custom CSS, zoals dat nu al gebeurt in het Forum, beter te faciliteren, zodat jullie je eigen tweaks makkelijker kunnen delen. Zodra we daarover iets concreters kunnen melden, laten we het weten.

Code:

1
2
3
4
5
6
7
8
9
10
11
12
#categoryBar, .fpAnkeiler {
   display: none;
}

table.highlights td {
  font-size: 12px;
  padding: 2px 0;
}

table tr.inBetweenContent {
   display: none;
}

Deze code past de frontpage aan naar de hieronder getoonde compactere nieuwsfeed.

Andere verbeteringen:

  • Het welkomstgeschenk voor Hero-abonnees is veranderd. Zij krijgen nu bij het afsluiten van een abonnement de exclusieve Tweakers Bamboo Coffee Cup.
  • We hebben productcategorieën toegevoegd voor usb, audio en videohubs, voor officesoftware en -suites, en voor servers.

Reacties (33)

33
33
26
4
0
2
Wijzig sortering
Vergeet niet de dependency nouwer neer te zetten dan 4.2.*, maar naar ~4.2.7 of 4.2.*,>=4.2.7, waar 4.2.7 de huidige versie (geldt voor elke dependency). Dit zorgt ervoor dat er minder versie constrains mogelijk zijn, waardoor composer minder geheugen gebruikt en veel sneller is; zie: https://github.com/composer/composer/issues/7273

Overigens zie ik dit niet aangegeven dus bij deze. De manier van upgraden van 3.4 maar 4.x dmv een nieuwe project lijkt mij zoals aangeraden door Flex. Mocht je geen flex gebruiken, heb je geen problemen om in dezelfde repository 4.2 te installeren. Dit komt omdat flex inhaakt op het installeren van bundles (en nu ook libraries volgens mij). Flex voegt dan o.a. default config toe in app/packages/*, en registreert je bundle in bundles.php. Dit gebeurd niet als de dependencies al geinstalleerd zijn. Je kan het wel forceren mocht je dat willen, zodat je deze manier van upgraden niet hoeft te doen.
De PHP Intl extensie werkt met ICU, dat is even wennen.

Op https://format-message.gi...e-format-for-translators/ word duidelijk uitgelegd hoe dit formaat werkt, en met https://format-message.gi...r-translators/editor.html kan je zelf experimenteren.
Het debuggen van x-debug is wel een verrekte knap staaltje debuggen :-) Erg leuk artikel :-)
Wel apart dat het dus betere prestaties oplevert om 2 keer een functie aan te roepen dan 1 keer aanroepen en in een variabele opslaan.
Nee, je mist een stapje ;)

Stel je hebt code alla:

if (simpeleExpressie && zwareExpressie) {
...
}

De compiler optimaliseert die code zo dat als uit de eerste simpele expressie 'false' komt hij nooit die tweede zware expressie zal uitvoeren. De code word door de compiler basically herschreven naar:

if (simpeleExpressie) {
if (zwareExpressie) {
..
}
}

En aangezien de eerste expressie een lokale variable is is die check ontzettend snel en zal de syscall naar getpid() nooit uitgevoert worden.

[Reactie gewijzigd door Kees op 23 juli 2024 14:57]

Maar zoals ik de bugfix lees gaan we van:

long pid = getpid()
if(pid == x) {}
..
if (pid == y) {}

naar:

if(getpid() == x){}
..
if(getpid() == y)

----------------------------
Dan roep je toch 2 keer getpid() aan, in plaats van hem in een variabele op te slaan?
Nee, we gaan van:

long pid = getpid();
if ((xdebug_is_debug_connection_active() && (XG(remote_connection_pid) != pid))) {

naar

if ((xdebug_is_debug_connection_active() && (XG(remote_connection_pid) != getpid()))) {

wat dus vertaald naar:
if ((xdebug_is_debug_connection_active()) {
if ((XG(remote_connection_pid) != getpid()))) {
...
}}

waarbij die getPid() call dus nooit uitgevoerd word als er geen debug connectie actief is. De commit kun je hier zien: https://github.com/xdebug...a4b50a647c8c71a8234839c73

[Reactie gewijzigd door Kees op 23 juli 2024 14:57]

Ah ik zie het. Slim!
Ik had zelf verwacht dat xdebug_is_debug_connection_active() altijd 'true' terug zou geven in jullie omgeving. Juist omdat je in een debug omgeving zit.
In dit geval is dat alleen 'true' als je 'remote debugging' actief hebt (en dan is hij dus wel 'traag'). Dus als je met phpstorm step-by-step wil debuggen. Dat doen we wel eens, maar 9999 van de 10000 keren dat zo'n script draait niet.
Het probleem kon uiteindelijk eenvoudig worden opgelost met een verandering van een paar regels code. Ondertussen is versie 2.7.1 van Xdebug uitgekomen, waarin de patch van Kees is meegenomen.
Bedankt Kees! _/-\o_
Ik hoop dat er een testcase wordt toegevoegd om regressie te voorkomen, anders komt deze case vaker voor.
Oftewel, een testkees :+
Ik hen inmiddels alle kees/case grappen voorbij horen komen, één van mijn collega's heet Kees :D
I rest my Kees
Ok, klaar... kees closed
Just in Kees, weet je het zeker?
Kan iemand mij vertellen hoe het opgelost is? Uit de patch haal ik zelf dat een opgeslagen resultaat van getPid() vervangen is door twee losse calls. Dat lijkt mij juist het tegenovergestelde effect te hebben.

Edit: vraag is hierboven beantwoord. Dit code pad wordt alleen doorlopen indien je remote debugging uitvoert, wat kennelijk zelden het geval is. Merk hierbij op dat veel talen short-circuit toepassen op if-statements; i.e. bij een '&&' wordt de rechter expressie alleen uitgevoerd indien de linker expressie 'true' geeft.

[Reactie gewijzigd door RuudAnders op 23 juli 2024 14:57]

Nu is custom CSS in de karmastore beschikbaar voor iedereen die minimaal 4096 karma in totaal heeft bereikt. En het blijft daarna ook actief.
Ik heb custom CSS ergens in Februari aangeschaft, maar heb nog geen 4096 karma totaal.
Verloopt mijn custom CSS dan alsnog?
Auteurikloon Product Lead @Bas17023 april 2019 15:38
Nee, het verloopt niet. Je houdt het gewoon.
Lekker bezig heren! Zag alleen nog een puntje dat niet klopt:
"Aanbieding: De geselecteerde waarde is geen geldige optie."
Op het moment dat je de Coffee cup selecteert en je door wil gaan naar de betaalpagina :)

[Reactie gewijzigd door TweakOverflow op 23 juli 2024 14:57]

Dit bleek een kleine bug met, gek genoeg, als oorzaak de Symfony 4 update. Inmiddels hebben wij het gefixed, bedankt voor het melden!
Nu is custom CSS in de karmastore beschikbaar voor iedereen die minimaal 4096 karma in totaal heeft bereikt. En het blijft daarna ook actief.
Onderstaande staat nog als tekst wanneer je de custom CSS wil aanschaffen.

Je staat op het punt om de feature "Custom CSS" aan te schaffen met de door jou verzamelde karma. Deze feature zal een halfjaar beschikbaar zijn (dus tot 23-10-2019) waarna je via de karmastore weer kunt verlengen. Je kan er ook voor kiezen om automatisch te verlengen, dan zal over een halfjaar deze feature automatisch opnieuw gekocht worden indien er op dat moment ook voldoende karma hebt gehaald in het komende halfjaar.

Ook na de aankoop word "https://tweakimg.net/g/edit.gif" geladen die niet bestaat.

[Reactie gewijzigd door Christoxz op 23 juli 2024 14:57]

Auteurikloon Product Lead @Christoxz23 april 2019 15:17
Oeps, foutje, bedankt. Is inmiddels gefixt.
Mooie update, goed beschreven. Wij werken vanuit een systeem in de energiemarkt ook nog met 3.4 en moeten ook eens dezer maanden naar 4 upgraden. Ook onze weg zal ons leiden langs de route die jullie hebben doorlopen. Kortom, mooi inzicht in hoe een ander groot team het aanpakt, bedankt!
De toepassing die voor het uitwisselen van custom css ben ik wel erg benieuwd naar. En wederom goed werk!
Mooi cadeau die Tweakers cup. Uniek, reclame, en toch ook milieuvriendelijk.

Op dit item kan niet meer gereageerd worden.