Debugging WSL Valet issues when using phpenv on Windows 10

Image of Windows 10, PHP and Nginx logos in a corner

Now, that title is a mouthful, no? 😅

Well, I’m writing this as a tutorial/reminder if anybody stumbles upon a similar issue as I have. I like to tinker around with my development setups. Sometimes it works. Other times it kinda breaks my computer and I need to rebuild everything from scratch. But hey, we learn the most that way (by tinkering with things, not breaking them down 😂).

Development setup

I’ve switched from Mac to Windows PC as my main development driver recently. I think it was mostly because my 2019 MBP cannot handle 4K displays at 60Hz, and working on 30Hz monitors really is a strain. It might seem like a first-world problem (and it kinda is), but if anybody ever had the same issue they know what I’m talking about. 30Hz just strains my eyes, it’s slow, etc.

Because I got really used to using the terminal, WSL2 was a great way to have a sort of a seamless transition from Mac to Windows.

The next thing I got really used to when working on Mac is Laravel Valet. It just works. No-fuss development. Luckily for me, there is a WSL version of it. I’ve installed it, and it worked (with a few hiccups, but it worked).

I also wanted to play around with new PHP (8), and this is where my story becomes a bit complicated. I’ve installed phpenv in order to quickly switch from one PHP version to another. And it worked. And all was well.

Until I realized that my CLI version didn’t correspond to my PHP-FPM version provided by Valet. So I started digging and realized that Valet depends on the native php installation – in my case the one you get by using apt-get to install the PHP. So while my CLI was running PHP 7.4.20, my WordPress installation reported 7.4.3. Which I thought was odd. So I removed all the instances of PHP that come natively installed, or which were added by Valet.

And everything broke down, kinda.

The problem?

Valet knows how to work with native extensions (on mac it uses Homebrew to handle packages), but not ones that use phpenv. So I removed and reinstalled it again, this time in the phpenv directory, which is located in ~/.phpenv/versions/7.4.20/composer folder. While working, kinda, it still threw some errors every time I tried to install or restart it

Warning: Class 'Tightenco\Collect\Support\Collection' not found in /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/tightenco/collect/src/Collect/Support/alias.php on line 19

Fatal error: Uncaught Error: Interface 'JsonSerializable' not found in /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/tightenco/collect/src/Collect/Support/Enumerable.php:11
Stack trace:
#0 /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/composer/ClassLoader.php(480): include()
#1 /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/composer/ClassLoader.php(346): Composer\Autoload\includeFile('/home/dzoljom/....')
#2 [internal function]: Composer\Autoload\ClassLoader->loadClass('Tightenco\\Colle...')
#3 /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/tightenco/collect/src/Collect/Support/Collection.php(11): spl_autoload_call('Tightenco\\Colle...')
#4 /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/composer/ClassLoader.php(480): include('/home/dzoljom/....')
#5 /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/composer/ClassLoader.php(346): Composer\Autoload\includeFile('/home/dzoljom/....')
#6 [internal function]: Composer\Autoload\ClassLoader->loadClass('Tightenco\\Colle...')
#7 [internal fu in /home/dzoljom/.phpenv/versions/7.4.20/composer/vendor/tightenco/collect/src/Collect/Support/Enumerable.php on line 11Code language: Bash (bash)

For some reason, I’ve still yet to decipher, it looks like Valet doesn’t recognize the PHP used from phpenv 🤷‍♂️.

The php and php-fpm service will be served from the .phpenv folder

~/.phpenv/shims/php
~/.phpenv/shims/php-envCode language: JavaScript (javascript)

But valet doesn’t seem to like that.

I started to get errors on my sites. And that’s not good, for all the obvious reasons.

The solution?

Restart the nginx and php-fpm manually.

First I restarted the nginx

sudo service nginx restartCode language: Bash (bash)

This restarted the nginx service, but I got ‘Bad gateway (502)’ error on my site.

Which points to PHP-FPM not working. So I restarted it

~/.phpenv/versions/7.4.20/etc/init.d/php-fpm restartCode language: Bash (bash)

Notice that I didn’t use sudo here. It won’t work if you add sudo (probably something to do with permissions).

This worked, as I got another error now on my site:

FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: 127.0.0.1, server: …

So something was wrong in the nginx config. Let’s dig some more. I checked at my config

 sudo nginx -tCode language: Bash (bash)

Which said

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

So my config is ok, but most importantly what this showed me is my config paths. Also, I noticed that my sites were located in the /etc/nginx/sites-available/valet.conf. Quick inspection of that file showed what the culprit was

server {
    listen 80 default_server;
    root /;
    charset utf-8;
    client_max_body_size 128M;

    location /41c270e4-5535-4daa-b23e-c269744c2f45/ {
        internal;
        alias /;
        try_files $uri $uri/;
    }

    location / {
        rewrite ^ /home/dzoljom/.config/composer/vendor/valeryan/valet-wsl/server.php last;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log /home/dzoljom/.valet/Log/nginx-error.log;

    error_page 404 /home/dzoljom/.config/composer/vendor/valeryan/valet-wsl/server.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index /home/dzoljom/.config/composer/vendor/valeryan/valet-wsl/server.php;
        fastcgi_buffering off;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /home/dzoljom/.config/composer/vendor/valeryan/valet-wsl/server.php;
    }

    location ~ /\.ht {
        deny all;
    }
}Code language: Nginx (nginx)

Notice the paths of the SCRIPT_FILENAME for instance. But my valet is no longer served from that path! It’s in /home/dzoljom/.phpenv/versions/7.4.20/composer.

Changing all the old paths with the new ones did the trick.

After restarting nginx and php-fpm for good measure all my sites were working.

That’s all good, but does’t seem so future proof…

That is true. It’s a bandage fix unfortunately. Next thing I need to find out is how to replace the hardcoded paths with current PHP versions set by phpenv. Since all the versions are inside the ~/.phpenv/versions folder, I think this could be somehow automated (at valet-wsl level).

Also, I noticed that the valet-wsl isn’t updated. And doesn’t support phpenv. So I forked the repo, and I’ll try to see if I can improve some things to make it work with phpenv seameslly.

I hope this article helps people who stumble on this odd problem like I had.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.