At some point I made a 'Data Abstraction Layer' (DAL) which could be combined with an extended class. It's sole purpose was to access specific entities by id and cache them. The extended class would define what entities were available as well as do any intermediate data massaging. It passed the data back as an array by reference. This way the receiving end could accept it as a reference and then modify it directly. Once something called the DAL's save method for an entity type it would loop over all rows, determine what rows had been changed or deleted, then update the database accordingly. It was quite a piece of work for 5+ years ago and only using PHP4.
I also made an 'SQL Generator' (query builder). Most of its parameters were specified as an array of arrays, each inner array being the specification for a table/row and some also including more information for comparison to another table/row. The tables required were all listed internally as new tables were requested in the 'where' parameters. The primary reason I made it was so I could modify queries already built depending on what was needed. Looking back on the code I'm not sure if it was a good or bad thing. Compared to the queries I was building it saved some effort and made it easier to copy parameters around to other statements, but compared to the way I write queries now those benefits are somewhat mute.