After three years at the day job I’ve been granted access to a physical escape key. I prefer a “build everything back by hand” approach to setting up a new laptop, and this includes pulling over two locally run PHP applications I use to automate my job. One’s a WordPress P2 instance I use to log my daily work, the other is a bespoke Laravel application I built to automate common drudgery during our two week “answer the questions support engineers can’t” rotations.
This is the first new laptop I’ve setup where I decided to go “full homebrew
” for PHP. In the past I used the liip project and it’s predecessor for PHP, and I installed a MySQL server directly from the MySQL project. I have a bias towards sticking with the projects that got me here — but homebrew
finally won me over with its support for multiple versions of PHP and an easier experience deploying PHP-FPM via brew services
.
Still — setting everything up turned into the dance of 1,000 paper cuts that modern PHP’s become.
PHP, MySQL, and Homebrew Paper Cuts
First, I forgot homebrew
‘s apache server is configured for port 8080
by default, and I had to do the “which PHP-FPM FastCGI VirtualHost
configuration will I use” dance (Servers for Hackers has the configuration I chose). I also had a brief fear and loathing moment where it seemed like apache’s proxy module was linked incorrectly but I’d enabled mod_proxy_fcgi.so
without enabling mod_proxy.so
and the result was missing symbols. I also did my usual 24 minutes of head scratching until I remembered “oh, right, all the directories above an apache root directory need to be executable”.
Using homebrew
to install MySQL seems to have brought MySQL 8 to my system. When I moved my databases over I forgot that mysqldump
‘s --all-databases
command includes systems tables, and importing them into a clean install on MySQL 8 wrecked things pretty good. Once I cleaned that up (by running brew uninstall mysql
, and then deleting data in /usr/local/var/mysql
) I got to play the MySQL legacy password game and update my accounts to use the old password system (PHP can’t seem to connect using anything else). Also, the venerable Sequel Pro is having all sorts of issues (timeouts, crashing) when it’s talking to this MySQL 8 instance. I’m living with the mysql
command line interface for now — but if I was doing PHP full time I’d be unsure whether to see if homebrew
can run MySQL 5.6 or some version of percona, chase down the SequelPro bugs, install MySQL workbench, or chase down a new MySQL GUI application.
WordPress P2 Paper Cuts
Leaving MySQL behind — when I installed my P2 instance, the PHP 7.4 I’d installed via homebrew
immediately started warning me about a bad regular expression. I’m apparently using the P2 classic theme which hasn’t had an update in few years. Some googling around showed me that there’s a new project named O2 and that Automattic’s commercial arm is selling hosted P2. I thought really hard about abandoning this for a text file — but in for a penny, in for a pound.
I started poking at the bad regular expression in P2
var $mentions_regex = '/\B@([\w-\.]+)\b/';
It looks like the intent of this regular expression is to match three distinct character classes
\w
-
\.
But in PHP 7.4 I was getting a warning about an invalid range
Warning: preg_match(): Compilation failed: invalid range in character class at offset 7
Which meant that something thought I wanted the range of characters between \w
and \.
. So was this a change in the regular expression engine? Better validation in the regular expression engine? Validation that PHP itself was doing before passing something into the regular expression engine? I didn’t have time to go on that particular snipe hunt so I changed the regular expression to be \w\.-
and hoped it was right — I wasn’t too worried since is a personal log for my eyes only.
But then PHP 7.4 seemed to be caching the warning. Was it the WordPress cache? Some sort of PHP object cache like APC? Or was it the new PHP 7.4 preloading? Smelling another snipe hunt, I installed PHP 7.3 via homebrew
$ brew install php@7.3
and used it instead. The same regular expression error was there, but this time the caching behavior I’d seen was gone and I could fix the regular expression.
Laravel Application Paper Cuts
Then I moved on to my Laravel application — I pulled it out of source control and was getting weird cipher related errors —
production.ERROR: RuntimeException: The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths. in /path/to/app/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php:43
but I’d forgotten the .env
file (where the cipher key is configured) wasn’t stored in source control. Annoying, but that’s the system sort of working.
More confounding was every SQL query failing with
local.ERROR: PDOException: SQLSTATE[42000]: Syntax error or access violation: 1231 Variable ‘sql_mode’ can’t be set to the value of ‘NO_AUTO_CREATE_USER’ in /path/to/app/vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php:150
My first naive thought was more MySQL 8 paper cuts — but after some digging and research into what sql_mode
was, and remembering my WordPress install could query fine (although WordPress doesn’t use PDO and Laravel does, was that related? sigh) — I finally realized that Laravel itself is setting sql_mode
, and that NO_AUTO_CREATE_USER
isn’t a valid value in MySQL 8. Laravel’s fixed this more recently. Once again citing “I don’t have time for this” I patched my local application and moved on.
Conclusions
This is, I suppose, all in the day of a life of a modern software developer — but it still bugs me that PHP’s ecosystem has become this complicated. As part of a job maybe it makes sense that this is just what you need to do to deliver software to the entire planet — but the barrier to entry that this sort of complexity brings makes me wonder why anyone starting out today would pick PHP over something like Javascript (same complexity, but easier to get started just building UIs), Python (solid software engineering pedigree), or boring old Java (runs the business infrastructure of the world).