Installing PHP on MacOS Monterey

Here is the solution to a problem faced by any PHP developer that has upgraded their Mac to Monterey only to then re-attempt to run their PHP-based application afterwards and get back the dreaded response:

php: command not found

😨

That’s not good! Did Apple get rid of PHP in their latest operating system? Surely not!

Me – an hour after upgrading my MacBook

Oh, I see, that’s exactly what they did.

Me – 5 minutes later after Googling it

Right, so, how do we fix it?

First things first, make sure you have Homebrew installed. Chances are you already do, it being similar to apt for most Linux distros, but it’s best just to check.

brew -v

If you get back something that looks like the below, then you have it installed, otherwise you’ll need to go and install it.

Homebrew 3.5.9
Homebrew/homebrew-core (git revision 3eda28188e5; last commit 2022-08-22)
Homebrew/homebrew-cask (git revision eacfe8f6c1; last commit 2022-08-22)

Right, so now, just brew install php right? Unfortunately, this won’t work in quite the way you’re expecting, so it’s best now to install a formula that actually allows for more versions of PHP to become available, than were available on older versions of MacOS anyway:

brew tap shivammatur/php

Now you can install it, the only caveat is that you need to specifically choose the version (unless it’s 8.0).

brew install shivammatur/php/php@8.1

Other options available are:

  • 5.6
  • 7.0
  • 7.1
  • 7.2
  • 7.3
  • 7.4
  • 8.0 – as above, you can remove the @ part for this version

Now you need to link it to the php command:

brew link --overwrite --force php@8.1

Where possible of course, I’d usually recommend using the latest available version.

Now all these changes mean we need to restart our terminal before PHP will work, so once you’ve done that run php -v and you should get back something like the below:

PHP 8.1.9 (cli) (built: Aug  4 2022 15:11:08) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.9, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.9, Copyright (c), by Zend Technologies

What if I want to change my PHP version?

You can change the PHP version that is installed and linked, but you will need to restart your terminal again after doing so. Let’s say I want to switch back to 7.4 for some reason:

brew install shivammatur/php/php@7.4

(You will only need to do the install step once.)

brew unlink php && brew link --overwrite --force php@7.4

Of couse, you need to unlink the command from its current destination before you can link it somewhere else!

But, wait, couldn’t I just use Docker?

Docker Moby Logo

In most cases, indeed you could! I’d actually recommend this method wherever possible, as you can spin up an image in moments with all the necessary dependencies, configurations, and of course PHP version for your project. However, my situation is rather unique (although maybe not as unique as I think) in that when accessing private Gitlab repositories for my company, even so far that I have to be connected to the company’s VPN to even access the login page, your SSH keys that are on your machine can’t then be used by a Docker container even if it is running on that same machine.

Docker also givs you the advantage of offering more versions. A lot more versions. A huge number of versions! A cursory glance at the tags available on the Docker Hub should give you an idea.

Conclusion

Is there a roadblock preventing you from using Docker, or a very good reason why you shouldn’t? Perhaps you haven’t learned Docker yet, luckily the learning curve is easy for beginners to get onto so I may well do an article on that as well (maybe even a video, I haven’t decided yet). If there is such a reason or roadblock, then go through the process I’ve described above. Otherwise, Dock away!

Oh, and, even if you do go down the Docker route, I’d still suggest at least completing the Homebrew step at the start of this post. A Mac without Homebrew is a bit like an internal combustion car without a gearbox, it will still work, but not nearly as well as it should!

CSS nth-child selectors

You can do all sorts of thing with nth-child selectors, such as selecting the first child element, 5th, 10th, 14th or even last, 2nd-last etc.and primarily that is what it was used for, but there are so many more thing you can (and probably would want to in certain situations) do besides…

Now I haven’t ever really come across anywhere on the web that has everything you can do with CSS nth-child selectors all in one place, so this is what I’m aiming to achieve.

Now there are 2 main flavours of child selectors in CSS, they are :nth-child(n) and :nth-of-type(n). :nth-child can be used on its own as it can simply select the nth child of, say a div element. Each of these can be used along with a selector, say, p:nth-of-type(n) or li:nth-child(n).

So what would be the difference be between p:nth-child(3) and p:nth-of-type(3)?

  • p:nth-child(3) will select a p element that is the 3rd element of its parent element. If the 3rd child of that parent element isn’t a p element, it simply won’t select anything.
  • p:nth-of-type(3) will select the third p element within the parent element, even if it is not the 3rd child, it could be the 4th, or the 15th. If there are fewer than 3 p elements within the parent element, it simply won’t select anything.
  • p:nth-child(3) and p:nth-of-type(3) will select the same p element if, and only if, we start off our parent element with 3 uninterrupted p elements.

So now that that’s out of the way, on to what we can do with the selectors!

Selecting all child elements

You may have, say, a div tag where you want to do something to each of its children, but not the div itself, for this you simply combine the div with the universal selector, which is *, for a result of div * {your style here}.

Selecting a certain child

The most simple thing to do is select a single child element based on its position within its parent element, for this we would use, for example, nth-child(4) to select the 4th child element.

A couple of important shortcuts are below with any more to follow:

  • :nth-child(1) = :first-child
  • :nth-of-type(1) = :first-of-type

Now we go on to selecting a subset of child elements. This is where the real fun begins…

Selecting a subset of child elements

Starting off with a really simple and common example – we have a table with a header row, and a few rows where we want to alternate the background colours.

The term itself – nth – has its roots in calculus, and as such we can use an expression such as 2n to select every even child element of a parent, a popular example is styling alternate rows in a table, for which you would use table tr:nth-child(2n). This means that our styling will apply to 2 x 0 = the 0th child (no such thing), the 2 x 1 = 2nd child, the 2 x 2 = 4th child, and so on until the 2nth child doesn’t exist i.e. we’ve reached the end of the table.

To select all the odd rows instead we can replace the 2n with 2n+1, so our styling will now apply to 2 x 0 + 1 = the 1st child, 2 x 1 + 1 = 3rd child, 2 x 2 + 1 = 5th child and so on, again until the 2n+1th child doesn’t exist.

As you may be suspecting at this point however, we again have some useful shortcuts:

  • :nth-child(2n) = :nth-child(even)
  • :nth-child(2n+1) = :nth-child(odd)
  • :nth-of-type(2n) = :nth-of-type(even)
  • :nth-of-type(2n+1) = :nth-of-type(odd)

Of course however there are far more subsets then just even and odd, what if we are wanting something a bit more advanced, like selecting every 4th child, or selecting every 5th child, starting at the 2nd one (so 2nd, 7th, 12th etc.)?

Luckily the 2 in 2n and 1 in, uh, 1, can be replaced by any integer, so if we wanted to select every 4th child it would simply be :nth-child(4n), if we wanted to select every 5th child starting from the second we’d start with :nth-child(5n) but then we’d need to “shift” it by adding -3, as 5 – 3 = 2, so our final result would be :nth-child(5n-3).

There aren’t any shortcuts for these particular setups unfortunately. However we can use them to create another 2 subsets: the first few child elements or all but those first few:

Selecting all but, or only, the first or last few elements

The way to select the first 5 child elements seems a bit counterintuitive, but it would be :nth-child(-n+5), as it would go through -0 + 5 = 5th child, -1 + 5 = 4th child, -2 + 5 = 3rd child and so on until it arrives at the 0th child which of course doesn’t exist. For selecting all but the first 5, we essentially want to start our selection at the 6th child, so this is a much simpler :nth-child(n+6).

Now we know how to select single child elements and subsets of those child elements, however there is one other thing that I myself have recently run into. All of our subsets have either started at the beginning or ended at the end, but what if we want a subset that starts and ends somewhere in the middle?

I came across this when doing a piece on SVG transformations and in particular matrices, a mathematical concept that is essentially a grid of numbers, so I used CSS grid to create my matrix, being a 3×3 matrix I simply called it matrix-3:

.matrix-3 {
    display: inline-grid;
    grid-template-columns: repeat(3, auto);
    grid-template-rows: repeat(3, auto);
}

Now I will want the first 3 children on the first row, the next 3 on the second and the final 3 on the third, as well as this I will want the 1st, 4th and 7th children in the 1st column, the 2nd, 5th and 8th children in the 2nd column, and the 3rd, 6th and 9th children in the 3rd column.

Now I could go through each child element, tell the first child to be in row 1 column 1, tell nth-child(2) to be in row 1 column 2 etc. or I could reduce 9 statements into 6 by starting off with nth:child(3n+1) {grid-column: 1;} to tell the first, 4th and 7th elements their column, then nth:child(3n+2) {grid-column: 2;} and finally nth:child(3n) {grid-column: 3;}.

Now we can select our first 3 elements no problem, and tell them to go into row 1, :nth-child(-n+3) {grid-row: 1;}, and our last 3 elements we can tell to go into row 3, :nth-child(n+7) {grid-row: 3;}. But how do we now select our middle 3?

Selecting a central subset of elements

i.e. one that doesn’t start at the beginning of our parent, or end at the end

The neatest (and so far only, so also messiest) way I have found of doing this is by doubling-up on our selectors, so starting with :nth-child(n+4) to give us the last 6 elements we can now add :nth-child(-n+6) to pick those elements that are also in the first 6, so we basically end up with :nth-child(n+4):nth-child(-n+6) {grid-row: 2;}. So think of it as chaining multiple nth-child selectors together as a sort of AND statement if you will.

So there we have it, everything (that I can think of at least) that you may want to do with CSS nth-child selectors!

Questions or comments? Or anything that you’d want to do with nth-child selectors that perhaps doesn’t appear in this post? Let me know in the comments below!