Larry GarfieldMuch ado about null (13.5.2022, 16:24 UTC)

Much ado about null

Submitted by Larry on 13 May 2022 - 11:24am

null has a controversial history. It's been called "the billion-dollar mistake" by its creator. Most languages implement null, but those few that do not (such as Rust) are generally lauded for their smart design by eliminating a class of errors entirely. Many developers (myself included) have argued that code that uses null or nullable parameters/returns is intrinsically a code smell to be avoided, while others (also myself included, naturally) have argued that is too draconian of a stance to take.

Anna Filina has a very good three-part series (properties, parameters, and returns) on how to avoid null in PHP generally. Alexis King has a related post (excuse the Haskell) on how to avoid needing edge cases like null in the first place.

However, I want to go a bit deeper and try to understand null from a different angle, and tease out the nuance of why one would really want to use it, and thus what we should be doing instead. To get there we'll have to go through a tiny little bit of type theory, but it will be quick and painless, I swear.

Continue reading this post on PeakD.

Link
Derick RethansXdebug Update: April 2022 (10.5.2022, 08:39 UTC)

Xdebug Update: April 2022

In this monthly update I explain what happened with Xdebug development in this past month. These are normally published on the first Tuesday on or after the 5th of each month.

Patreon and GitHub supporters will get it earlier, around the first of each month.

You can become a patron or support me through GitHub Sponsors. I am currently 46% towards my $2,500 per month goal. If you are leading a team or company, then it is also possible to support Xdebug through a subscription.

In April, I spend 29 hours on Xdebug, with 27 hours funded.

Development

I continued my exploration of different set-ups that developers user, and have created a prototype branch that adds support for the "pseudo-host" xdebug://gateway which can be used with the xdebug.client_host setting instead of, and in addition to the Docker specific host.docker.internal. This pseudo-host automatically evaluates to the network gateway address in the container, which will then allow Xdebug to connect to an IDE on the host machine.

This value will work for:

  • PHP/Xdebug running in Docker on Linux, Windows, and macOS; with the IDE on the host.

  • PHP/Xdebug running in WSL, with the IDE on the (Windows) host.

  • PHP/Xdebug running in Docker in Ubuntu on WSL, with the (Linux) IDE running in WSL.

It will not work where network isolation is used, for example with the following set-ups:

  • PHP/Xdebug running in root-less Docker on Linux, IDE on (Linux) host

  • PHP/Xdebug running in Docker for Windows in WSL, with the Linux version of the IDE inside WSL.

I have not figured out how to do it will all different set-ups, so if you have extra information, or if I am still missing set-ups, feel free to comment on the Google Doc.

In the more complicated set-ups, it would likely be easier to use Xdebug Cloud as it has none of these networking complications.

Course

I have spend a fair amount of time developing the Xdebug course, with the first lesson now written and ready to be recorded. I have decided to include a "Tech Corner" with each lesson, to explain how Xdebug interacts with PHP to do the things that are explained in each lesson. Hopefully you'll find this interesting as well. It will also serve to reduce the bus factor.

For further lessons I have started to draft outlines, and they are in different states of completion.

If you want to make sure that the course covers specific tasks that you find hard to do, or what you would like explained, please drop me an email, or leave a comment.

Xdebug Recorder

I have been making little progress as I have been focused on developing the course. There is a persistent bug while creating the recording, which is hard to track down, as it only happens occasionally and does not seem to be easily reproducible.

You can follow the development in the recorder branch.

Xdebug Cloud

Xdebug Cloud is the Proxy As A Service platform to allow for debugging in more scenarios, where it is hard, or impossible, to have Xdebug make a connection to the IDE. It is continuing to operate as Beta release. Packages start at £49/month.

If you want to be kept up to date with Xdebug Cloud, please sign up to the mailinglist, which I will use to send out an update not more than once a month.

Truncated by Planet PHP, read more at the original (another 1332 bytes)

Link
Matthew Weier O'PhinneyTailwindCSS Tips (26.4.2022, 19:15 UTC)

I've been dabbling in CSS my entire career. In the early days, it was relatively simple, as our browsers were fairly limited. But over the years, CSS has become more and more capable, allowing styles to target only tags with specific tag attributes, only apply at specific screen sizes, and even perform complex layouts using things like flexbox and grid. I take a bit of time every now and then to understand these things... but since I don't use CSS a ton, it's hard to keep up.

As such, over the past decade, I've tended to use CSS frameworks, and generally Bootstrap. Every couple years, a new major version is dropped, and I have to learn new structures and components, and struggle to get things to look the way I want. Worse, when I use these frameworks, injecting custom CSS often means understanding how the framework is already styling components so I can ensure things don't conflict.

The last couple years, I've been keeping an eye on TailwindCSS. I've been a bit skeptical, as its declarative, utility-first approach looks a lot like doing CSS inside your HTML, which, honestly, feels off. I've typically subscribed to the idea of semantic HTML, which advocates separating style from markup. Having styles directly that mimic CSS directives associated with every tag feels like an unholy mix, and a far cry from semantic HTML.

And then there's the hype. The original author and project lead of Tailwind is a huge hype man, and hype tends to turn me off. That's on me, not them, but having been in the business for over two decades, I'm finding I'm more and more likely to discount hyped products and projects, because I've seen them come and go so frequently; there's often an indirect relationship between the amount of hype and the long-term viability of a project. I've also often observed that hype serves as a way for users to deflect reasonable critique, and the more vehement the user base, the less interested I am in engaging with them because of this. Clearly, YMMV, but it was definitely something keeping me from really investigating Tailwind.

However, recently, in helping out the PHP Foundation, I volunteered to setup their static website, and the team requested using TailwindCSS, so I dove in.

And I discovered... I kind of love it.

This is one of those "I'll be googling this in the future" posts.

How it works

I won't go into how to get started with Tailwind; their docs do a great job of doing that for you. However, I will give a quick overview of how things work, so you can see (a) where I'm coming from, and (b) what you'll be doing when you start with Tailwind.

The way I've always learned to do CSS is to first write HTML, and then write CSS to style that HTML the way you want it to appear.

<div class="box">
  <h2>Title</h2>
  <p>Some content</p>
</div>

<style>
.box {
  margin: 0.5rem;
  background-color: #333333;
  border: #000000
  padding: 0.5rem;
}

.box h2 {
  background-color: #dedede;
  padding: 0.5rem;
  color: #111111;
  font-size: 2rem;
  min-width: max-content;
}

.box p {
  padding: 0.5rem;
  font-size: 1.2rem;
  min-width: max-content;
}
</style>

Tailwind instead provides a ton of "utility" classes, targetting just about every CSS directive. You then add these HTML classes to elements to style them:

<div class="m-2 p-2 bg-neutral-600 border-black">
  <h2 class="min-w-full p-2 bg-neutral-300 text-4xl text-neutral-800">Title</h2>
  <p class="min-w-full p-2 text-xl">Some content</p>
</div>

Behind the scenes, you run the Tailwind CLI tool, and it analyzes your HTML to generate CSS for you. You can even have it watching for filesystem changes to files you're interested in (templates, JS scripts, etc.), and it will regenerate the CSS automatically.

Tip 1: Layers

Out of the box, Tailwind does a CSS reset that removes all styles. This is great, because it means that any changes you make, you can anticipate exactly what will hapen. It's also a pain in the ass, because everything is unstyled: your headings look just like your paragraphs, your lists look just like your paragraphs, and there's no way to tell where one paragraph ends and another begins.

So, the first thing you'll want to do is define your base styles. Tailwind has a very specific suggestion for where and how to do this: in the "base" layer.

Opening your site CSS file, you'll see these directives when you begin:

@tailwind base;
@tailwind component

Truncated by Planet PHP, read more at the original (another 14308 bytes)

Link
Pascal LandauCI Pipelines for dockerized PHP Apps with Github & Gitlab [Tutorial Part 7] (25.4.2022, 07:00 UTC)

In the seventh part of this tutorial series on developing PHP on Docker we will setup a CI (Continuous Integration) pipeline to run code quality tools and tests on Github Actions and Gitlab Pipelines.

All code samples are publicly available in my Docker PHP Tutorial repository on github.
You find the branch for this tutorial at part-7-ci-pipeline-docker-php-gitlab-github.

All published parts of the Docker PHP Tutorial are collected under a dedicated page at Docker PHP Tutorial. The previous part was Use git-secret to encrypt secrets in the repository and the next one will be Deploy dockerized PHP Apps on a GCP VM.

If you want to follow along, please subscribe to the RSS feed or via email to get automatic notifications when the next part comes out :)

Table of contents

Introduction

CI is short for Continuous Integration and to me mostly means running the code quality tools and tests of a codebase in an isolated environment (preferably automatically). This is
particularly important when working in a team, because the CI system acts as the final gatekeeper before features or bugfixes are merged into the main branch.

I initially learned about CI systems when I stubbed my toes into the open source water. Back in the day I used Travis CI for my own projects and replaced it w

Truncated by Planet PHP, read more at the original (another 87889 bytes)

Link
Pascal LandauUse git-secret to encrypt secrets in the repository [Tutorial Part 6] (25.4.2022, 06:00 UTC)

In the sixth part of this tutorial series on developing PHP on Docker we will setup git-secret to store secrets directly in the repository. Everything will be handled through Docker and added as make targets for a convenient workflow.

git-secret example

FYI: This tutorial is a precursor to the next a part Create a CI pipeline for dockerized PHP Apps because dealing with secrets is an important aspect when setting up a CI system (and later when deploying to production) - but I feel it's complex enough to warrant its own article.

All code samples are publicly available in my Docker PHP Tutorial repository on github.
You find the branch with the final result of this tutorial at part-6-git-secret-encrypt-repository-docker.

All published parts of the Docker PHP Tutorial are collected under a dedicated page at Docker PHP Tutorial. The previous part was Set up PHP QA tools and control them via make and the following one is Create a CI pipeline for dockerized PHP Apps.

If you want to follow along, please subscribe to the RSS feed or via email to get automatic notifications when the next part comes out :)

Table of contents

Introduction

Dealing with secrets (passwords, tokens, key files, etc.) is cl

Truncated by Planet PHP, read more at the original (another 53907 bytes)

Link
Pascal LandauSet up PHP QA tools and control them via make [Tutorial Part 5] (25.4.2022, 05:00 UTC)

In the fifth part of this tutorial series on developing PHP on Docker we will setup some PHP code quality tools and provide a convenient way to control them via GNU make.

Run QA tools

FYI: Originally I wanted this tutorial to be a part of Create a CI pipeline for dockerized PHP Apps because QA checks are imho vital part of a CI setup - but it kinda grew "too big" and took a way too much space from, well, actually setting up the CI pipelines :)

All code samples are publicly available in my Docker PHP Tutorial repository on github.
You find the branch with the final result of this tutorial at part-5-php-qa-tools-make-docker.

All published parts of the Docker PHP Tutorial are collected under a dedicated page at Docker PHP Tutorial. The previous part was Run Laravel 9 on Docker in 2022 and the following one is Use git-secret to encrypt secrets in the repository.

If you want to follow along, please subscribe to the RSS feed or via email to get automatic notifications when the next part comes out :)

Table of contents

Introduction

Code quality tools ensure a baseline of code quality by automatically checking certain rules, e.g. code style definitions, proper usage of types, proper declaration of dependencies, etc. When run regularly they are a great way to enforce better code and are thus a perfect fit for a CI pipeline. For this tutorial, I'm going to setup the following tools:

and provide convenient access through a qa make target. The end result will look like this:

QA tool output

FYI: When we started out with using code quality tools in general, we have used GrumPHP - and I would still recommend it. We have only transitioned away from it because make gives us a little more flexibility and control.

You can find the "final" makefile at .make/01-02-application-qa.mk.

CAUTION: The Makefile is build on top of the setup that I introduced in Docker from scratch for PHP 8.1 Applications in 2022, so please refer to that tutorial if anything is not clear.

##@ [Application: QA]

# variables
CORES?=$(shell (nproc  || sysctl -n hw.ncpu) 2> /dev/null)

# constants
 ## files
ALL_FILES=./
APP_FILES=app/
TEST_FILES=tests/

 ## bash colors
RED:=\033

Truncated by Planet PHP, read more at the original (another 37861 bytes)

Link
Larry GarfieldA robust, powerful, easy to use attribute parser for PHP (21.4.2022, 21:56 UTC)

A robust, powerful, easy to use attribute parser for PHP

Submitted by Larry on 21 April 2022 - 4:56pm

After sitting on it for a while, I am pleased to release a PHP library for robust, powerful attribute handling in PHP 8.1: Crell/AttributeUtils. It's a robust, centralized tool for slicing, dicing, and reverse engineering classes in PHP using attributes.

The basics

The basic model of Attribute Utils is to analyze a class "with respect to" some attribute. That attribute may be defined on the class, or not. (Both options have meaning.) That attribute may be associated with attributes on properties or methods, which are all scanned together to produce a picture of a class.

Continue reading this post on Hive.

Link
Matthias NobackDDD entities and ORM entities (21.4.2022, 09:00 UTC)

I was tweeting something about having separate "DDD" and "ORM" entities in a project in a project, and that I don't understand this. There were some great comments and questions, thanks a lot for that! To be honest, I understand more about it now. In this article I'll try to provide some more information about this.

I'm glad many developers want to use input from the book "Domain-Driven Design" by Eric Evans to improve their domain model. I recommend reading this book and getting your information from the source, because unfortunately the internet, tweets, e-books, including my own books, aren't able to reflect a full, nor a correct view of everything there is to find out about this topic. All too often DDD is completely misinterpreted to be "an elitist, dogmatic approach to programming, where we use DTOs, layers, and CQRS"...

I think some programmers, myself included, want to escape from the framework-coupled, hype-inspired mess that web application development often seems to be. Unfortunately, while trying to move in the opposite direction, they end up with a lot of code that is written for the sake of decoupling. Or maybe it happens because they want to try something new and not-boring, something that can't be generated from the command-line with make:entity.

Back in the days when Symfony 2 adopted annotations for routing, and Doctrine ORM did the same for its mapping configuration, I was one of the first to be against that, pointing out that it's "framework coupling". I mean, "Are you coupled to the framework?!"

Ever since I've been thinking, experimenting, and writing a lot about this topic (e.g. my book about application architecture, and an older article about ORMless). In the end I think our applications need framework coupling in certain areas, and in other areas, like the domain model, they are better off being decoupled.

But full decoupling is usually not the best choice. Rather, 80% decoupling is fine ;) As an example, it seems that some would like to have DDD entities that are fully decoupled from the ORM. They interpret this to mean that you can't have ORM annotations in your entity, or that you can't use specialized collection classes like Doctrine ORM forces you to have. This coupling is by no means dangerous, and certainly doesn't get in the way, as long as:

  • We can instantiate and modify these entities without a runtime dependency on the database.
  • We can retrieve data from these entities without a runtime dependency on the database.

Once this is the case, you can even test their behavior in a unit test, because these are the only requirements for that. It does mean that most entities-in-the-wild aren't good entities, because calling methods on them is most likely to trigger database queries (e.g. lazy-loading for child entities or referenced entities). If you use an Active Record implementation like Eloquent, many more methods will trigger database queries.

And this is where DDD comes in, with its aggregate design rules. I often refer to an excellent series of articles on this topic, by Vaughn Vernon. In summary:

  • An aggregate should guarantee its own consistency, establishing relevant domain invariants (i.e. it should prevent itself from being in an invalid or incomplete state).
  • Reference other aggregates by their ID (i.e. don't pass related entities as objects, or load them lazily).
  • Aggregates should be small (i.e. don't let it manage child entities or related entities).

We can learn a lot from these DDD patterns to make our models better, and we can in most cases accomplish this while using our current ORM and its entities or model objects. We just upgrade these existing objects with insights from the DDD book; adding intention-revealing methods, making state changes in meaningful chunks instead of on a per-field basis, throwing exceptions whenever a consistent state is in danger, etc. There may be some things we have to do to please the ORM, but nothing that messes up much with our domain model. A good rule of thumb is to focus on the public methods of the entity, and ignore what goes on behind the scenes (good old encapsulation).

There is one situation where upgrading existing ORM entities to DDD entities isn't going to work: when you want to evolve the design of your aggregates, without also evolving the database schema. I don't have experience with this. Whenever

Truncated by Planet PHP, read more at the original (another 1503 bytes)

Link
Larry GarfieldPHP Tricks: Multi-value match() (19.4.2022, 16:41 UTC)

PHP Tricks: Multi-value match()

Submitted by Larry on 19 April 2022 - 11:41am

Last time, I talked about fun uses of the match() expression in PHP, using unconventional types of expressions on the right-arm branch. This time, I want to expand that discussion to include fun tricks on the left-side of the `=>`, and how you can easily match by multiple values at the same time.

I'm going to assume you have read the previous installment about how match() works and what an "expression" means. Also, I don't claim to be the original source of these tricks. I'm just documenting them because they're cool. Let's dive in.

Continue reading this post on Hive.

Link
Larry GarfieldPHP Tricks: Uncommon match() expressions (15.4.2022, 18:15 UTC)

PHP Tricks: Uncommon match() expressions

Submitted by Larry on 15 April 2022 - 1:15pm

Recently, I've been helping a new developer out in a chat room. He's still learning PHP and working through tutorials, with lots of questions along the way. Earlier this week, by accident, he stumbled across a use of match() statements I'd not considered before. While technically not right for his use case, it did suggest another, potentially valid use for match() I'd not seen. Let's add it to the list of cool things you can do with match().

Continue reading this post on Hive.

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP