I posted before that I started a query languages library. I knew it would have some iterations, but I wanted to take others along in the process.
The pivotal moment for me was adding MongoDB to the library. I made quite a few changes, and it became clear I needed to split up the library. So that is why I will not commit any more on the current repository.
In this post I want to elaborate on the changes that are coming and the lessons I learned.
The name
I choose composable queries because it was a mix of the diversity of database systems I want the library to accommodate. And the way you can use the library by exposing a lot of the inner workings through the use of functions …
I posted before that I started a query languages library. I knew it would have some iterations, but I wanted to take others along in the process.
The pivotal moment for me was adding MongoDB to the library. I made quite a few changes, and it became clear I needed to split up the library. So that is why I will not commit any more on the current repository.
In this post I want to elaborate on the changes that are coming and the lessons I learned.
The name
I choose composable queries because it was a mix of the diversity of database systems I want the library to accommodate. And the way you can use the library by exposing a lot of the inner workings through the use of functions instead of objects.
I think identifiable queries is a more suitable name going forward. The core of library revolves around the IdentifierInterface. The goal from the start was to have a separation between the names of the data in the application and in the database. With ORM’s that is the task of objects. But I didn’t want the baggage a class brings with it, so I landed on enumerations.
While the name is not the most important part, I want to get it right.
The package separation
I mentioned it already in an update in my previous post. The reason is simple, functions are loaded up front.
If I made the library with objects it would have taken me longer realize I needed to split up the library. Because I would have known the objects are only loaded when they are used, so this also means that the dependencies that the library requires will only be used when needed. But I realized this is not good if I want to create a more utilitarian library.
So I’m going to create a core library package and a package per database system. The database system package will have a core package dependency. The biggest advantage I see in this structure is that database packages can be as close to the actual database systems as possible. This is one of the main problems of ORM libraries, they only provide wrappers for the common functionality of the database systems they target.
A common language
While the functionality of database systems varies, I still want to provide a level of comfort by reusing function names for different database systems. The best example for now is the PDO getStatement, Redis getStatement and the MongoDB getStatement functions. While the functionality is a little different between the different databases, the main function stays the same.
Not throwing exceptions
With the release of PHP 8.5 and the pipe operator feature so close. I wanted to provide a way to use the feature the best way possible.
This means returning exceptions, the main problem with that is you don’t want a match in every function to be prepared for every exception a previous function in the chain can output.
This is reason I created the Error object.
As soon as a function returns an Error instance, the other functions in the chain short circuit and pass that instance to the end of the chain.
When you look at the code you will see quite a few functions with similar code.
if ($statement instanceof Error) {
return $statement;
}
The bonus of not throwing exceptions is that the return type of the function is complete. If you throw exceptions you need DocBlock comments to make third party tools aware of the behavior of the function.
Next steps
When I separated the packages I’m going to add them to Packagist and provide documentation for each package. In the beginning it could get a bit messy because I’m still thinking about where the best place for certain functions is.
I never felt “building on the shoulders of giants” more as with this library. There are so much great things I learned along the way, that are the foundations of the ideas behind the library.