Detecting cyclic arrays in PHP – A new approach

Part 2 of series Detecting cyclic arrays in PHP.

In Part 1 of this series I explained the problem of detecting cyclic arrays, and why it cannot be done in pure PHP. I also promised to present a solution that is both simple and correct for all possible arrays, which is what this post is about. But before that, let me restate the definition of cyclic arrays from the previous post: An array is cyclic if iterating all of its items and subitems does not terminate.

Here is an example of a cyclic array:

$array = [1, [2, 3]];
$array[1][1] = &$array;
Continue reading “Detecting cyclic arrays in PHP – A new approach”

Why it is impossible to detect cyclic arrays in pure PHP

Part 1 of series Detecting cyclic arrays in PHP.

This post is about a problem that might only be relevant to a small minority of PHP programmers who maybe want to write a custom serializer, or something else that requires recursively iterating an array. But, in trying to solve it, I found some interesting PHP weirdness that I think is worth highlighting.

As an aside:
If you are just looking for a reliable solution for detecting cyclic arrays – and you want to miss out on learning about some cool (but also complicated) PHP quirks – then skip to Part 2 of this series.

First of all, let’s define our terms. For the purpose of this post, we can espouse a very pragmatic definition: An array is cyclic if iterating all of its items and subitems does not terminate. Cyclic arrays are also sometimes called circular or recursive. Let’s look at some examples:

// Contains a reference to itself
$v = [1, 2, 3];
$v[1] = &$v;

// Contains a nested array that contains a reference to $x
$x = [1, [2, 3]];
$x[1][1] = &$x;

// Contains a nested array that contains a reference to an ancestor
$y = [1, [2, [3, 4]]];
$y[1][1][1] = &$y[1];

// Contains a nested array that contains a reference to itself
$z = [1, [2, 3]];
$z[1][1] = &$z[1];

I think you get the idea. All of these arrays contain a cycle at some level.

Continue reading “Why it is impossible to detect cyclic arrays in pure PHP”

Overriding Composer packages at the source level

I think we all have been in that situation where we had to extend some library class but there was something preventing us from doing it the normal way. A common example of this would be overriding private methods, or accessing private variables, or dealing with final classes. Another maybe less obvious case is when the class you want to extend is a hardwired dependency for code that you have no control over. In that that case, even if everything were public and overridable you would not be able to inject your subclass.

The scenario

In a previous blog post I wrote about wanting to override the function cleanBindings on the Builder class (source) from the Laravel framework. Extending the class itself is no problem because the function is public and the class is not marked final. The real problem here is that the Builder is a hard-coded dependency multiple levels deep in the framework code.

Now, as a disclaimer, there are other ways to accomplish this task that are a lot more conventional than what I am about to show you. And I generally do not recommend that you use my solution for production code. With that out of the way, let’s look at the mechanism.

Continue reading “Overriding Composer packages at the source level”

Postgres Arrays and PHP -Part 1

The other day I found myself designing a database schema for a collection of musicians each of which plays one or more instruments. The result looked something like this.

CREATE TABLE musicians
(
    id bigserial NOT NULL,
    name text NOT NULL,
    PRIMARY KEY (id)
);

CREATE TYPE musical_instrument AS ENUM
    ('guitar', 'piano', 'bass', 'trumpet', 'drums');

CREATE TABLE musician_instruments
(
    musician_id bigint NOT NULL,
    instrument musical_instrument NOT NULL,
    "position" integer NOT NULL,
    PRIMARY KEY (musician_id, instrument)
);

As you can see the table musician_instruments is used to associate musical instruments to a musician. It has an additional column called position because the order of instruments is relevant for the application.

When I squinted real hard I saw that I had in front of me a simple array disguised table. So I thought, why not use the array type that Postgres provides and see where it leads me. A research project if you might.

ALTER TABLE public.musicians
    ADD COLUMN instruments musical_instrument[] NOT NULL;
Continue reading “Postgres Arrays and PHP -Part 1”

Add columns with custom types in Laravel Migrations

I was certainly surprised when I found out that there is no built-in method to create table columns with custom types in Laravel migrations. The default list of column types available in Laravel may be more than enough for most applications, but, I think there are some valid use cases for opening the hood and directly working on the engine.

The scenario

Many DBMS offer non-standard column types that you might want to use to unlock some untapped potential. For me this was adding support for PostgreSQL’s built in enumerated types (enums) and arrays. Now, I am not claiming that using these particular types is generally a good idea (especially arrays). As always, you need to evaluate the upsides and downsides for your specific application.

Continue reading “Add columns with custom types in Laravel Migrations”