— Artikel — № 050

050 —Workflow

Twee schermen, één blik: FTP en MySQL bij legacy sites

Op een verouderde PHP-site zit de bug bijna altijd op de naad tussen bestandssysteem en database. Hier lees je waarom je de twee nooit los koppelt.

Bovenaanzicht: twee vellen op linnen, inkt-FTP-boom en ER-diagram verbonden door rode draad, messing SEAM-plaatje ertussen.
Hero · gestileerd stilleven№ 050

Een dinsdagmiddag. Een klant mailt: "de meta description op /diensten noemt nog steeds de oude bedrijfsnaam." Je opent het themabestand. Het loopt door de wp_get_document_title-filterketen. Nergens een verwijzing naar de oude naam. Je opent wp_options, draait SELECT option_value FROM wp_options WHERE option_name = 'blogdescription'. Daar staat hij. Oude naam, voor het laatst aangeraakt in 2019.

Twee vensters. Eén vraag. Vijf seconden.

Dit bedoelen we met de twee-schermen-gewoonte op een legacy site. Niet letterlijk twee monitors, al schelen die wel. Het is het mentale model waarbij je bestandssysteem en database in hetzelfde gezichtsveld houdt, want op een 12 jaar oude PHP-installatie vertelt geen van beide je in zijn eentje de waarheid.

De splitsing die je ogen al maken

In een nieuwe Next.js- of Rails-app heeft "waar staat deze string?" één antwoord. In een oude WordPress-site heeft die vraag er zes. De string kan staan in de header.php van het actieve thema, in een child theme dat de parent overschrijft, in de wp_options-tabel, in wp_postmeta via Yoast of Rank Math, als constante in wp-config.php, of in een .htaccess-rewrite die de URL stilletjes naar een heel andere pagina aliast.

De code lezen zonder de data te lezen is het halve verhaal. De data lezen zonder de code te lezen is de andere helft. De meeste bugs op een legacy site zitten op de naad daartussen.

De vier opzoekacties die elk uur terugkomen

Houd jezelf een dag in de gaten terwijl je aan een legacy WordPress-site werkt. Vier patronen blijven terugkomen.

Code verwijst naar een meta-key, jij controleert de waarde. Een template draait get_post_meta($id, '_custom_layout', true). Jij queryt:

SELECT meta_value
FROM wp_postmeta
WHERE post_id = 412
  AND meta_key = '_custom_layout';

Leeg. Daarom valt de layout terug op de standaardwaarde.

Een rij verwijst naar een bestand, jij opent het bestand. wp_options.template zegt twentytwentyone-child. Je opent /wp-content/themes/twentytwentyone-child/style.css en de parent-declaratie wijst naar een thema dat drie jaar geleden is verwijderd.

Een 500 in de browser, een stack trace in het log, een config in de rij. Apache-logs zeggen Allowed memory size of 134217728 bytes exhausted in /wp-includes/class-wp-query.php. De fix zit in wp-config.php via ini_set('memory_limit', '512M'), maar de oorzaak is misschien een op hol geslagen query tegen een wp_postmeta-tabel die inmiddels tot 1,4 miljoen rijen is gegroeid.

Er duikt uit het niets een redirect op. De pagina geeft 200 terug op databaseniveau, 301 in de browser. De regel staat ofwel in .htaccess:

RewriteEngine On
RewriteRule ^old-url/?$ /new-url [R=301,L]

of in een wp_redirection_items-tabel van een plugin, of in wp_options.siteurl dat naar een vervallen domein wijst. Je controleert alle drie voor je hem vindt.

Stuk voor stuk twee-venster-klussen. Het ene venster is de FTP-tree. Het andere is een SQL-prompt.

Eén scherm, op de juiste manier gesplitst

Niet iedereen heeft het bureau voor twee schermen. De gewoonte werkt prima op één scherm zolang je de splitsing aanhoudt. De ene helft is de bestandsbrowser en editor. De andere helft is de database-client. Je tabt er niet tussendoor. Je kijkt opzij.

Een paar tactische opmerkingen na jaren werken op deze manier, dwars door legacy WordPress, Drupal 7, Joomla 3 en Magento 1 heen:

  • Houd de FTP-tree opengeklapt tot /wp-content/. Daar zit 90% van de antwoorden. De core-mappen veranderen zelden. Stamp wp-content/themes, wp-content/plugins, wp-content/uploads en wp-content/mu-plugins in je geheugen.
  • Pin vier query-templates vast. Eén voor wp_options op naam. Eén voor wp_postmeta op post-ID. Eén voor SHOW CREATE TABLE op elke tabel die je niet herkent. Eén voor wp_users op login. De meeste dagen heb je verder niks nodig.
  • Lees .htaccess één keer aan het begin van elke sessie. Vertrouw daarna nooit op je geheugen ervan. Elke legacy site heeft een .htaccess die iemand in 2017 half heeft bewerkt en nooit heeft opgeruimd. De Apache RewriteRule-docs zijn de enige bron van waarheid op het moment dat de volgorde van flags geen hout meer snijdt.
  • Open wp-config.php in alleen-lezen. Daar worden constanten gedeclareerd die de database niet kan zien, en waarden overschreven waarvan de database denkt dat ze er zelf de baas over is. WP_HOME, WP_SITEURL, $table_prefix. Als de prefix is gerandomiseerd, breekt elke query-template hierboven totdat je hem aanpast.

Waarom de gewoonte zich uitbetaalt

De reden dat dit telt is niet dat het tijd bespaart op één enkele opzoekactie. Het bespaart tijd op de opzoekactie waarvan je nog niet wist dat je hem nodig had. Zodra bestandssysteem en database in dezelfde oogopslag zitten, zie je de naad zonder erover na te denken. Je merkt op dat het template een optie verwacht die er niet staat. Je merkt op dat de databaserij verwijst naar een bestand dat is hernoemd. De mismatches komen visueel boven, niet via deductie.

Dit is het stuk dat zich niet laat vertalen naar werken op een verse stack. In een moderne app worden schema en code in sync gehouden door migraties en ORM's. In een legacy PHP-site werden ze in sync gehouden door een developer die in 2018 vertrokken is, en sindsdien zijn ze uit elkaar gedreven. Jij bent nu de migratie. Jouw ogen zijn de diff.

Toen we Pier bouwden liepen we hier bij iedere klantinstallatie tegenaan. Wat we uiteindelijk hebben gedaan is de bestandstree en de MySQL editor in hetzelfde venster zetten, naast elkaar, met version history die de wijzigingen aan beide kanten tegelijk bijhoudt. De naad blijft zichtbaar zonder dat je alt-tabt, en dat is precies het punt van de gewoonte.

Het kleinste wat je vandaag kunt proberen: open je huidige legacy-project, splits de editor zodat de bestandstree naast een SQL-prompt staat, en draai één query tegen wp_options voor een optie-naam waar je actieve thema naar verwijst. Wat je ook vindt, het vertelt je iets dat de code niet liet zien.

— Vragen —

Heb ik hier echt twee fysieke monitors voor nodig?

Nee. Eén scherm dat fiftyfifty is gesplitst tussen een FTP-bestandsboom en een SQL-editor werkt prima. De gewoonte zit in de layout, niet in de hardware.

Waarom niet gewoon de WordPress-admin gebruiken om instellingen op te zoeken?

De admin verbergt waarden, normaliseert geserialiseerde data, en laat je geen verweesde rijen zien. wp_options rechtstreeks lezen is sneller en eerlijker over wat er werkelijk opgeslagen staat.

Werkt deze gewoonte ook op moderne stacks?

Minder. Moderne stacks houden schema en code in sync via migraties. Op legacy PHP zijn die jaren geleden uit elkaar gegroeid, en dan wordt de visuele diff tussen bestandssysteem en database je debugger.