Setting up Laravel Valet + MySQL via Homebrew

After far too much delay, I’ve finally ditched MAMP Pro. It’s taken me too long really, that software is decidedly… not nice.

I’m now trying Laravel Valet + MySQL via Homebrew for local PHP development on my MacBook Pro. See notes below for future reference. I had some fiddly points getting started and expect there to be more, but am pretty pleased with the change overall.


0. Back up databases

The pre-step is to back up any preexisting databases so that you can set them up later if needed. Personally, I use Sequel Pro for all local and some remote database management, so I pulled my necessary exports from there.

1. Install and configure Laravel Valet

The first step is to install Laravel Valet. Their installation docs are pretty much all that is needed. The only caveat is that I’d be a little careful about updating Homebrew or Composer willy nilly, just be wary if you already have it installed and need your preexisting version for any reason. While completing the installation steps, pay attention to the warnings! Complete any recommended steps if you can, they pop up for a reason.

If all went well, at this point you should have an Apache server so you’d be ready to work on a file-based website such as one that uses Kirby CMS or a static site generator (Hugo, Gatsby, Jekyll, etc).

2. Install and configure MySQL with Homebrew

To work on a database-driven site like a Craft CMS or WordPress build, the next step is to install MySQL via Homebrew.

The Laravel Valet docs mention this step, but for me it was nowhere *near* as simple as their two-command recommendation. I think there was likely a conflict with my preexisting MAMP-specific MySQL setup and possibly an old Homebrew installation. I ran the commands from the Valet docs to install MySQL v5.7 and run it, but I would get the error The server requested authentication method unknown to the client [caching_sha2_password] on the front-end. This error indicated that it was actually running MySQL v8 (read more). Sure enough, mysql --version returned mysql Ver 8.0.16 for osx10.14 on x86_64 (Homebrew). To sort it out, I had to reinstall and restart the MySQL service.

To remove MySQL, I followed these instructions. (Be careful with those commands, they remove a lot of stuff.)

After I’d gotten rid of MySQL, I ran the commands below to install, link, and start the service.

brew install mysql@5.7
brew link --force mysql@5.7
brew services start mysql@5.7

Note that I tried doing this without the link but consistently ran in to the error Can't connect to local MySQL server through socket '/tmp/mysql.sock' when trying to connect in the next steps. Linking seemed to sort it.

After this, I followed the installation’s recommendation and ran mysql_secure_installation. This is so that we set the root user’s password since it is required for phpMyAdmin and Sequel Pro (coming up next).

3. Set up and / import databases

Once MySQL is set up and running, it’s time to configure the databases. To do this via the command line, run mysql -u [username] -p [databasename] < [filename.sql] (replace bits in brackets) and when prompted, enter the password you set up via mysql_secure_installation.

Otherwise, you can do it via a UI such as phpMyAdmin (see Laravel Valet-friendly steps) or Sequel Pro.

4. Adjust PHP settings (optional)

I usually adjust my PHP settings (e.g. memory_limit, max_execution_time, post_max_size, etc.) per-project so that they’re closer to the site’s production hosting environment. I thought it would be as simple as adjusting the php.ini file that is specified in the “Loaded Configuration File” value returned by phpinfo(). I edited /usr/local/etc/php/7.2/php.ini and then ran valet restart to restart the server and… it didn’t work. One of my changes was respected according to phpinfo(), but the rest weren’t.

I checked the “Additional .ini files parsed” value and saw that the file /usr/local/etc/php/7.2/conf.d/php-memory-limits.ini was also in use. After I edited this file to include my preferred settings and restarted Valet, all was well.

5. Adjust Nginx config (optional)

Valet’s default Nginx config should normally be sufficient, but you might have to tweak it for certain edge cases.

My edge case was the British Earways site (read more). I was working with it locally and suddenly ran in to a 413 Request Entity Too Large error when attempting to upload a very large audio file. To get around this, I needed to raise the client_max_body_size Nginx directive.

To adjust the Nginx configuration, I first had a look at the main config file by running /usr/local/etc/nginx/nginx.conf. Scanning through that, I saw a few includes:

include "/Users/[username]/.config/valet/Nginx/*";
include servers/*;
include valet/valet.conf;

I had a look at valet.conf, found client_max_body_size and changed that value to suit my requirements, and then restarted the server by running valet restart.

Other useful things

  • Run brew services list to find out which services are running. This is useful for troubleshooting if you’re having PHP or mySQL errors.
  • If you’re adjusting the PHP settings in a .ini file, run valet restart, and then suddenly start seeing only an “It works!” screen where your site should be, you probably have to stop Apache first before restarting Valet. Most guidance online recommends running apachectl stop, but I had trouble with this (see related StackOverflow thread). Instead, I ran valet stop, sudo killall httpd, then valet start. This worked smoothly
  • Here’s a list of MySQL commands.
  • For more info about what $PATH is and why it’s important, see this Unix & Linux Stack Exchange thread.
  • I usually use redirect rules to use media from production when developing locally. Laravel Valet doesn’t seem to play nice with the normal .htaccess method, maybe because it’s actually an Nginx server. See “Proxying images to a remote host on Laravel Valet” for an effective alternative.

Edit 10 July 2019 – Added further notes based on working with Laravel Valet the past few days, including the PHP and Nginx config adjustments.

britishearways.com

Screenshot of britishearways.com

Last month, I completed a major overhaul of the British Earways website. The design by Valerio di Lucente of Julia is almost entirely unchanged, the adjustments were largely performance-related and under the hood, geared towards modern browsers. Here’s brief rundown of the changes:

  • Style the full-window player layouts using CSS Grid Layout + 100% height (not 100vh since that can lead to unexpected behaviour on mobile browsers), and use CSS Scroll Snap w/ polyfill for scroll behaviour
  • Achieve flexible typography and spacing with “CSS Locks
  • On non-touch screens, implement invisible DragDealer instances so that each player’s scrubber can be dragged
  • On touch screens, add click event listeners that advance the relevant scrubber to the click target
  • Use styled HTML5 progress elements for each player since these are easily manipulated via their max and value attributes and don’t require adjustment if the window is resized
  • Use the Web Audio API to initialise each audio file and trigger the necessary state changes as the time updates
  • Switch the audio preload attribute from auto to metadata to reduce the size of the page when it initially loads
  • Update CMS to Kirby 3 (this was a joy, IMO the panel layout options make v3 much more client-friendly)
  • Adjust post_max_size, memory_limit, max_execution_time, and upload_max_filesize to allow upload of large (150MB+) audio files

I ran in to one issue that isn’t yet resolved. Kirby copies all uploaded media from the private /content folder to the publicly-accessible /media folder. This copying normally happens almost instantly, even with very large files. On the BE site however, the copy is pretty slow. Since the site pulls the audio duration from the audio file itself via the Web Audio API, the displayed duration is incorrect until the file has finished copying. This is almost certainly related to some rate limiting done by the shared hosting company, a legacy from the preexisting site. It isn’t a huge deal since the copying always finishes eventually, but it isn’t the best behaviour. I’d like to raise the issue with the hosting company but don’t have high hopes, shared hosting providers use rate limiting for a reason.

At any rate, I’m really looking forward to seeing how DB uses the site over the next year and listening to the new mixes.

Site update: a new taxonomy index and a11y improvements

Just pushed an update to this site.

The Browse page is now mainly an index of taxonomies and archives (years, post formats, categories, tags). This new index replaces the opacity-based tag cloud. I kind of miss it, but it was problematic. Very hard to digest, and the lighter greys were way too low-contrast.

Besides the index, most of the changes are related to accessibility. I focused on making the tabbing experience a bit better, introducing a couple skip links. Note that I haven’t totally ironed out the tabbing… Most of my manual testing for this update was done in Chrome. I checked it briefly in Safari and it’s pretty weird, but I think it may have to do with the default Safari settings. I haven’t adjusted these yet, read more about Safari tab settings on a11yproject.com. Besides the tabbing, I also had a handful of links that weren’t suitably descriptive, particularly on the new term index. I added more aria-label attributes where I could. See the “Using aria-label for link purpose” page on the WCAG wiki for more info.

I’m trying to work on accessibility a bit more on an ongoing basis. Need to take a little dive in to this Hacker News thread, via this tweet.

See also:

There are probably a million a11y optimisations I can / should still make on this site. Suggestions are very welcome.

Resolving Craft 3 Setup Wizard error

I keep encountering issues when running Craft’s setup command locally. Note that I use MAMP Pro for this sort of thing. I entered all the database creds correctly, and then got a SQLSTATE[HY000] [2002] No such file or directory error. This StackExchange answer sorted it for me. Add 'unixSocket' => getenv('DB_SOCKET') to /config/db.php and DB_SOCKET="/Applications/MAMP/tmp/mysql/mysql.sock" to .env.

Still encountering database connection issues on staging for one site currently under development. All of the credentials are set correctly in .env, but getenv() in /config/db.php retrieves the wrong DB_USER value. Ended up explicitly adding the problematic value to the /config/db.php file as a quick workaround, but it’s not ideal.

WordPress security resources

Links to a few of the security resources I find useful, some WordPress-specific and some more general.

A note about that “step-by-step” guide: it’s pretty decent, but IMO Wordfence is a better security plugin to go with. Sucuri is maybe more user-friendly, but Wordfence comes with more out-of-the-box (incl. two factor authentication and login limiting) and the settings seem more granular. Doesn’t hurt to try both though to see what’s the best fit.


Last edited 22 June 2019

Website updated

piperhaywood.com 

Finally updated my website to include information and links for a few recent projects. Sam and I worked together to redesign the site. In return, I helped him move his domain to sambaldwin.info.

I’m quite excited about the colour of the text and favicon. The hue, saturation, and lightness are calculated according to the season, temperature, and time of day where I am.

There’s definitely a couple of issues to sort out, will get to those soon.

WordPress function for images with ‘srcset’ attribute

Wrote a function returning an image element with srcset and sizes attributes. See this Gist for the function and this Gist for an example of the function in use (would need to be within the WP loop).

Wanted to give a front-end dev like Sam the ability to define the important bits, including the default image size for the src attribute, the media queries for the sizes attribute, and classes for the img element if necessary.

Edit 23 Jan 2019
This isn’t necessary anymore, responsive images have been part of WP core since v4.4. They’re implemented on wp_content automatically via a filter. Use their related functions if you need to do something custom. Responsive images are behaving a little erratically on my site though, so will have to take a look at why that might be happening.