How I decided to write ORM in php from scratch on a working site, and what came of it

I, like many programmers, have a rather negative attitude towards the creation of bicycles and the invention of wheels, and this is more than justified at least by the cost of development for the business. But as my experience has shown, sometimes you have to deviate from this rule and, even, benefit from it. I mean not only interest and pleasure in development, but also goodies for the project as a whole. You can read a few words about one of my similar experiences under the cut.







Introduction



The way we create web applications now is very different from the code that came to us for support from ancient times, when the Star Factory was shown on TV, it was fashionable to walk with a clamshell , and PHP was just beginning to acquire signs of an Object-Oriented language. Programming in the 2000s seems to me to be an excellent illustration of Darwin's ideas: at that time, almost any single developer created his own solutions, some of them captured the minds of more than one person, and after passing through accelerated natural selection, frameworks and CMS became the title examples of the best and most popular development methods ... In some cases, nevertheless, only popular, without the word "good" or even more so "the best".





But unlike dinosaurs and mammoths, not all alternative solutions have gone into oblivion, especially on the backend, and I know this firsthand. I had a chance to work, I will not say with a large, but quite solid amount of legacy in php. Some of it was just awful and some of the sites and even the CMS were pretty interesting. Sometimes I like to delve into what was born in the minds of the pioneers. There was no such standardization back then, and although most of the time it is an excellent material for learning anti-patterns, but this code amuses me, makes the job similar to IT archeology.



Beloved legacy



Personally, I like working with working sites on legacy - to make an edit, remove some wild crutch, reduce the level of chaos and at the same time not break the whole system. At such moments I feel like a person who made this world a little better, and it's cool.



print " <button onClick='domultimove();' class=controlbutton><img src=syspix/ico32_move.gif border=0><br></button>";
print "<b>" . $ITEM->Description . "</b>:<br>";
$browsebgcolor = "#D9D9D9";
$sql = "select i.ID, m.Name, i.perm, i.descr from item4 i inner join main m on i.ID=m.ElementID";
echo "<script language='JavaScript'> document.location='" . $_SERVER['PHP_SELF']";


A common feature of legacy is a mess of code written in different languages, although in modern development, of course, we can add, for example, code in SQL to PHP classes. But I'm talking about something else, in legacy there is often a stream of universal thought of the developer - what and in what language he thought, he wrote in a stream. I want to talk about a similar situation with one mega-old-school CMS solution that I have been working with for some time. Everything there was so “wonderful” that I’m just very glad that I was able to fix something and make the site work much more correctly and faster.



So, I got a site for a large company, written in the first half of the 2000s. In this project, everything was based on classes with one method, in which everything happened: working with logic, and displaying the interface (view) and accessing the database, moreover, sql was right there between the commands
print "<table>";
... Making edits to a site running on such code, by the way, with good traffic and a commercial component, was not the most pleasant, but very fun event.





It’s easy to guess that I made the life of backend developers a lot easier by first bringing the layout output into templates. For this I used the ready-made and rather popular twig template engine. It was easy and fast, so I didn't even spend much time refactoring it. The next step, in my opinion, was to do something with queries to the database, after all, MVC is not in vain so popular in our web.





After looking at Symphony and Laravel, I decided that the ORM approach would fit perfectly here too. It will help to carry out work with the Database and leave for the time being not-to-controllers only work with the data already received. It is logical and completely correct to use existing solutions. Therefore, first of all, I rushed to packagist to see what alternatives I have besides Doctrine, but after thinking carefully, I came to the disappointing conclusion that it is not so important. The point is that this project had a rather unusual data structure. I have not seen such a thing anywhere else, although I worked with MODx :) I faced a problem: using popular open-source ORMs the way I want will not work, well, at least it will be another adventure. So I decided to create a bicycle.



A little about what I did





Yes, I decided that I would write an ORM in PHP from scratch (no, well, I had ideas and concepts borrowed from the same Docktrine) specifically for this project, so that it worked with the data structure. After all, this is a working site, and no one was ready to allocate programmers' resources for the task of “rewriting everything from scratch with a normal database structure”. The forefathers who founded this CMS created 2 types of objects, and one of them was also divided into internal "data types": resources that have dates, links, different types of text, images and a number of other types were stored in 2 tables, but there were also objects stored in one table, I think they can be called system data.





I didn't want to have to think about joins when applying calls to models, or at least try to reduce such moments to a minimum. Therefore, I decided that the models should be of two types: for single-table objects and for basic two-table objects. Since these Model-classes have many common methods, the same ORDER BY or LIMIT, therefore, each base class, on the basis of which concrete Models will be created, I inherited from the general Abstract class.



ORM



As you can see from the tree, I also added support for different types of Databases, which is redundant in this case. But at that moment I entered the "stream" and created :). Also, the very correct step in this case was that I did it on the basis of PDO, because the php-mysql used in the code did not allow translating the site into the seventh version of the language, and I wanted to fix this at the root, as they say.



$element = (new Model())->getOne($id);


Due to the fact that I had a good understanding of the logic of the structure of the Database, I managed to search and retrieve a resource only by its ID, without even knowing what internal data type the resource has, which was necessary with the old approach. Real object work with data, and we forget about sql in the code.





Final paragraphs ...



This work brought 2 unexpected turns for me. First, I tried to write everything at once in the form of code, and nothing worked. I had to take a pen, a notebook, go out into nature and, to the chirping of sparrows and the buzzing of bees, first draw what I want to get, how it will be connected, what classes I need, and how it will be called in the “controllers” code. By the way, then the implementation differed from the original sketches only slightly. So if the programmer doesn't code anything, it doesn't mean that he doesn't do anything useful.



Secondly, I did it very quickly, many businesses do not like it when programmers spend time on all sorts of incomprehensible refactorings. I implemented the entire project within about a week, while simultaneously doing the tasks for the implementation of new features.



I will note those advantages that I stated at the beginning of the article: the sequence and gradualness of replacing existing code on a working project, which means that there is no need to allocate more time for the transition, refactoring the code within the framework of incoming tasks. On this I take my leave, thank you for reading.



All Articles