Switching Between PHP Versions on MacOS

When switching between different PHP projects (or different branches of one PHP project), you often need to switch PHP versions. Particularly as older libraries will not run on newer versions of PHP. After losing patience with how the otherwise excellent Homebrew handles this, I stumbled upon this super-useful tool: switch-php.

This seems to have been written for PHP developers and integrates brilliantly with Laravel Valet. Here’s an example of switching from PHP 7.3 to 7.2:

Three Rock in the Fog

A quick New Year’s walk up to Three Rock and the Fairy Castle in the fog this morning.

UI Tests with Laravel Dusk for IXP Manager

We use standard PHPUnit tests for IXP Manager for some mission critical aspects. These take data from a test database filled with known sample data (representing a range of different member configurations). The tests then use this information to generate configurations and compare these against known-good configurations.

This way, we know that for a given set of data, we will get a predictable output so long as we haven’t accidentally broken anything in development.

But, as an end user, how do you know that what you stick in a web-based form gets put into the database correctly? And conversely, how do you know that form represents the database data correctly when editing?

This is an issue we ran into recently around some checkbox logic and a dropdown showing the wrong selected element. These issues are every bit as dangerous to mission critical elements as the output tests we do with PHPUnit.

To test the frontend, we turn to Laravel Duskan expressive, easy-to-use browser automation and testing API. What this actually means is that we can right code like this:

We have now added Dusk tests for UI elements that involve adding, editing and deleting all aspects of a member interface and all aspects of adding, editing and delete a router object. Here’s an example of the latter:

Laravel Dusk - Animated Gif Example

Repeal the 8th – Why I’m Voting Yes

I’ll be voting yes to repeal the 8th amendment to the Irish Constitution next Friday. Here’s why:

1) I, like 99% of the population, have never found myself in a situation where the termination of a pregnancy needed to be considered. This is a very fortunate position to be in. I then have to ask myself – with about zero personal experience or understanding of the emotional, physical, societal or financial turmoil involved in such a decision – who am I to tell any person that they may not have that option available to them in their own country?

2) Ireland has a long dark history of the socially conservative right and the religious orders trying to impose their moral beliefs on the rest of us. This has led to scandal after scandal: paedophile priests and its cover ups; Magdalene Laundries; the Tuam babies; the failure to liberalise contraceptives until 1992; the ban on divorce until 1996.

The broken families and the ruined lives left in the wake of these people should have taught us by now to stop allowing one section of society impose its moral beliefs on another. Let each of us weigh up our own individual situations, in the light of our own beliefs, and then make the best decision we can for ourselves.

3) Abortion is available to the majority of Irish woman as it stands – they travel to England (or further) and undergo the procedure there. It’s usually done in secret and without the support of a wider network of family, friends and medical oversight. If the 8th is not repealed, this status quo remains.

And this status quo, more than anything else, continues to marginalise the poorest and least resourceful amongst us. Being able to travel for a termination requires: money, the emotional wherewithal to organise it, a job that enables you to take the time required, possibly child care for existing children. This was something that most poignantly expressed in a tweet I saw recently: “My yes is for my younger self who ended up pregnant & then miscarrying as a consequence of rape. I would not have survived if the pregnancy had. I had no capacity to travel, I was too traumatised& poor, I was alone. I am not unique, I am too common.” I cannot speak to the providence of the tweet but we know from the alphabet soup of court cases that this is all too real.

4) For Savita Halappanavar and all other woman in a similar situation. It is a matter of fact that our laws killed this woman. If she was granted a termination when she requested it, Savita would be alive today. The ‘no side’ have tried to disgustingly twist and mangle the facts of this case.

5) For all the women and couples who have their foetus diagnosed with a fatal foetal abnormality. Under our existing laws, these women are either forced to carry the foetus to term or given information about travelling for a termination. They further suffer the injustice of having the remains delivered to them some time later by courier. Our children will look back at this and wonder what kind of dark age their parents lived in.

6) Speaking of dark ages and a reason that stands alone in its own right: the ‘X case’. Courtesy of and edited from Wikipedia: The case involved a fourteen-year-old girl who was a ward of the state and who had been the victim of a statutory rape by a neighbour in December 1991 and became pregnant. X told her mother of suicidal thoughts because of the unwanted pregnancy, and as abortion was illegal in both Ireland, the family planned to travel to the United Kingdom for an abortion. Before the planned abortion was carried out, the family asked the police if DNA from the aborted foetus would be admissible as evidence in the courts, as the neighbour was denying responsibility.

Hearing that X planned to have an abortion, the Attorney General sought and was granted an injunction under the Constitution (which outlaws abortion) preventing her from having the procedure carried out. The injunction was appealed to the Supreme Court, which overturned it.

X miscarried shortly after the judgement.

Unfortunately that case/situation has other awful twists and turns.

7) Consider this: The World Health Organisation has called for the provision of abortion in the public health system in Ireland. The United Nations Human Rights Committee has stated that the Irish abortion law violates the human rights of women here. The European Court of Human Rights made a similar ruling in the ‘C’ case. Ireland is the only country in the democratic world to have a conditional ban on abortion. Malta is the only other country in the EU with a complete ban on abortion.

Sometimes it’s good to be different. This is not one of those times.

8) For each of the A, B and C cases, Ms D,  Ms P and Ms Y. Sometimes you need to wonder what kind of fucking country we live in at all.

9) For my wife and daughter.


Have any arguments of the ‘no side’ resonated with me? No, I can’t say they have. I am a sufficiently intelligent person to be able to look dispassionately at both sides of the debate and their arguments. I may be advocating a yes vote but it doesn’t mean I exist in an echo chamber – far from it, I enjoy radio and debate most when my positions are being challenged.

If you’re on the ‘no side’ and it’s your a true and core belief to you that life begins at conception them that’s a view and a position I can understand and respect. But here’s some of the problems that the ‘no side’ have from my perspective:

10) There’s no sense of realism for what a yes vote would result in. The rhetoric is that of “pro-abortion” rather than pro-choice. If you believed some of those on the ‘no side’, a Saturday night out in 2019 would be to grab a bite to eat, head out for a few pints, have sex, wake up and get a quick abortion before brunch. I have not seen a single person on the ‘yes side’ who is ‘pro-abortion’. Every sane mature person knows that an abortion is a serious decision with life long consequences and no one undertakes that lightly nor is it anyone’s first choice.

11) The emotionally charged language – for example “our pre-born boys and girls” – grates heavily with me. I know when I’m being emotionally manipulated and I’m afraid it has the opposite effect.

12) It’s the same old tired faces of the social conservatives: the rural  wing of Fianna Fáil; John Waters, Mattie MaGrath, Breda O’Brien, Declan Ganley and Ronán Mullen; the Íona Institute with David Quinn and Maria Steen. With some of these, you turn on your television / radio and you’re brought back to referendums past. Or it feels like you’re being preached at from the pulpit.

13) The hysterics and the stunts. My Twitter feed is a fairly healthy mix of ‘yes’ and ‘no’ campaigners. But it feels like it’s the ‘no side’ with the biggest stunts (crosses along the road in Donegal, ‘NO’ on Benbulben) and throwing the biggest fits of hysterics: what looks like a clerical error becomes deliberate planned mass voter registration fraud; every poll result is either a farce or shows ‘a trend to no’; MEDIA BIAS; organised mass Tweets to presenters because MEDIA BIAS; ‘posters disappearing’. It’s tiring folks, really really tiring.

14) The hypocrisy and the continued enforcement of one set of beliefs. “Don’t trust our politicians, this is just the beginning.” Future politicians could of course tighten or remove abortion rights – that’s the power of how we’re changing the constitution. But of course the ‘no side’ know that the arc of time generally pushes us away from the darker oppressed ages they cling to. And of course the hypocrisy being that they tell us not to trust our own elected politicians but would rather allow Irish women to travel to England and entrust British politicians with their healthcare.

15) The latest attempt to muddy the waters seems to be to ask who are / were the Citezen’s Assembly. Christ on a bike. It doesn’t matter! Each of them, like the rest of us, have a single vote in this referendum!

Mostly, the ‘no side’ feels like a campaign that doesn’t have argument and reason on its side and so it falls back to aggression, emotional blackmail, whinging and the hysterics and the stunts mentioned above.

Here’s a fact: I have seen previous ‘no voters’ that have been turned into ‘yes voters’ citing the ‘no campaign’. I know of no single ‘yes voter’ that’s been turned into a ‘no voter’ by either campaign. The ‘no campaign’ should reflect on that in how they conduct themselves.

Doctrine2 with GROUP_CONCAT and non-related JOIN

Doctrine2 ORM is a fantastic and powerful object relational mapper (ORM) for PHP. We use it for IXP Manager to great effect and we only support MySQL so our hands are not tied to pure Doctrine2 DQL supported functions. We also use the excellent Laravel Doctrine project with the Berberlei extensions.

Sometimes time is against you as a developer and the documentation (and StackOverflow!) lacks the obvious solutions you need and you end up solving what could be a single elegant query very inefficiently in code with iterative database queries. Yuck. 

I spent a bit of time last night trying to unravel one very bad example of this where the solution would require DQL that could:

  1. group / concatenate multiple column results from a one-to-many relationship;
  2. join a table without a relationship;
  3. ensure the joining of the table without the relationship would not exclude results where the joint table had no matches;
  4. provide a default value for (3).

Each of these was solved as follows:

  1. via MySQL’s GROUP_CONCAT() aggregator. The specific example here is that when a MAC address associated with a virtual interface can be visible in multiple switch ports. We want to present the switch ports to the user and GROUP_CONCAT() allows us to aggregate these as a comma separated concatenated string (e.g. "Ethernet1,Ethernet8,Ethernet9").
  2. Normally with Doctrine2, all relationships would be well-defined with foreign keys. This is not always practical and sometimes we need to join tables on the result of some equality test. We can do this using a DQL construct such as: JOIN Entities\OUI o WITH SUBSTRING( m.mac, 1, 6 ) = o.oui.
  3. This is as simple as ensuring you LEFT JOIN.
  4. The COALESCE() function is used for this: COALESCE( o.organisation, 'Unknown' ) AS organisation.

We have not yet pushed the updated code into IXP Manager mainline but the above referenced function / code is not replaced with the DQL query: